Написание операторов SQL для таблиц с 2 ветвями - PullRequest
0 голосов
/ 27 июля 2011

У меня есть набор таблиц, подобный следующему

A ---- B_has_A ---- B ---- C ---- D_has_C ---- D
                           |
                           | ---- E_has_C ---- E

Я пытаюсь написать запрос, который позволяет мне объединяться A, B, D вместе, а затем из этого всего набора данных выбратьте, которые содержатся в D и E.

Я написал запрос, который может найти все вещи из ветви "E":

SELECT DISTINCT B.module, B.controller, B.action, B.object_only, B.description, privileges.object_id, A.A_id
  FROM C JOIN(
    B
    LEFT JOIN (
      B_has_A JOIN A
      ON A.A_id = B_has_A.A_id)
    ON (B.B_id = B_has_A.B_id))
  ON (C.B_id = B.B_id)
JOIN (E JOIN E_has_C)
  ON (E.E_id = E_has_C.E_id AND C.C_id = E_has_C.C_id)
  WHERE E.E_id IN (2,3)

Я также могу написать тот, где я могунайти вещи из ветки "D":

SELECT DISTINCT B.module, B.controller, B.action, B.object_only, B.description, privileges.object_id, A.A_id
  FROM C JOIN(
    B
    LEFT JOIN (
      B_has_A JOIN A
      ON A.A_id = B_has_A.A_id)
    ON (B.B_id = B_has_A.B_id))
  ON (C.B_id = B.B_id)
JOIN (D JOIN D_has_C)
  ON (D.D_id = D_has_C.D_id AND C.C_id = D_has_C.C_id)
  WHERE D.D_id IN (1, 2)

Как мне написать запрос, который может получить мне все из веток "D" и "E"?Я попытался использовать объединение, но оно не работает, и MySQL говорит, что есть синтаксическая ошибка:

SELECT DISTINCT B.module, B.controller, B.action, B.object_only, B.description, privileges.object_id, A.A_id
  FROM C JOIN(
    B
    LEFT JOIN (
      B_has_A JOIN A
      ON A.A_id = B_has_A.A_id)
    ON (B.B_id = B_has_A.B_id))
  ON (C.B_id = B.B_id)

JOIN (D JOIN D_has_C)
  ON (D.D_id = D_has_C.D_id AND C.C_id = D_has_C.C_id)
  WHERE D.D_id IN (1, 2)

JOIN (E JOIN E_has_C)
  ON (E.E_id = E_has_C.E_id AND C.C_id = E_has_C.C_id)
  WHERE E.E_id IN (2,3)

Любые указатели приветствуются:)

РЕДАКТИРОВАТЬ: окончательное решение.

Спасибо всем.Много хороших идей.Мое окончательное решение было похоже на "соединения ypercube" без использования круглых скобок:

SELECT ... long list
   FROM
     C    
   JOIN      
     B        
      ON C.B_id = B.B_id

   LEFT JOIN
     B_has_A
      ON B.B_id = B_has_A.B_id

   LEFT JOIN
     A
       ON A.A_id = B_has_A.A_id

   LEFT JOIN
      D_has_C
         ON C.C_id = D_has_C.C_id

   LEFT JOIN
      D
         ON D.D_id = D_has_C.D_id

   LEFT JOIN 
      E_has_C
         ON E.E_id = E_has_C.E_id

   LEFT JOIN
      E
         ON AND C.C_id = E_has_C.C_id

    WHERE E.E_id IN (2,3) OR D.D_id IN (1,2)

Там довольно много объединений, так что если кто-нибудь сможет пролить свет на то, как производительность этого сравнивается с подзапросом, этобыло бы здорово! :) 1022 *

Ответы [ 3 ]

0 голосов
/ 27 июля 2011

Вы пробовали вместо:

JOIN (D JOIN D_has_C)
  ON (D.D_id = D_has_C.D_id AND C.C_id = D_has_C.C_id)
  WHERE D.D_id IN (1, 2)

JOIN (E JOIN E_has_C)
  ON (E.E_id = E_has_C.E_id AND C.C_id = E_has_C.C_id)
  WHERE E.E_id IN (2,3)

это:

JOIN (D JOIN D_has_C)
  ON ((D.D_id = D_has_C.D_id AND C.C_id = D_has_C.C_id) AND D.D_id IN (1, 2))

JOIN (E JOIN E_has_C)
  ON ((E.E_id = E_has_C.E_id AND C.C_id = E_has_C.C_id) AND  E.E_id IN (2,3))
0 голосов
/ 27 июля 2011

Вы также можете попробовать удалить круглые скобки:

  SELECT ... long list 
  FROM
      C
    JOIN
      B
        ON C.B_id = B.B_id
    LEFT JOIN 
      B_has_A
        ON B.B_id = B_has_A.B_id
    JOIN 
      A
        ON A.A_id = B_has_A.A_id
    JOIN 
      D_has_C
        ON C.C_id = D_has_C.C_id
    JOIN
      D
        ON D.D_id = D_has_C.D_id
    JOIN
      E_has_C
        ON E.E_id = E_has_C.E_id
    JOIN
      E 
        ON AND C.C_id = E_has_C.C_id 
  WHERE E.E_id IN (2,3)
    AND D.D_id IN (1,2)

Это зависит от того, как соотношения 1-ко-многим между вашими таблицами, но вам, вероятно, понадобится GROUP BY C.C_id, и тогда вы можете удалитьDISTINCT.


ОБНОВЛЕНИЕ

«Таблица из таблицы D или E» предлагает что-то с EXISTS:

  SELECT B.module, B.controller, B.action
       , B.object_only, B.description, A.A_id 
  FROM
      C
    JOIN
      B
        ON C.B_id = B.B_id
    LEFT JOIN 
      B_has_A
        ON B.B_id = B_has_A.B_id
    JOIN 
      A
        ON A.A_id = B_has_A.A_id
WHERE EXISTS
  ( SELECT *
    FROM     
      D
    JOIN 
      D_has_C
        ON D.D_id = D_has_C.D_id
    WHERE C.C_id = D_has_C.C_id
      AND D.D_id IN (1,2)
  ) 
  OR EXISTS                        <--- Note the "OR"  
  ( SELECT *
    FROM
      E 
    JOIN
      E_has_C
        ON E.E_id = E_has_C.E_id
    WHERE C.C_id = E_has_C.C_id
      AND E.E_id IN (2,3)
  )
0 голосов
/ 27 июля 2011

Вы можете объединить результаты обоих запросов с UNION . Объединение может использоваться только для объединения определенных строк таблиц, а не целых наборов результатов.

SELECT DISTINCT B.module, B.controller, B.action, B.object_only, B.description, privileges.object_id, A.A_id
  FROM C JOIN(
    B
    LEFT JOIN (
      B_has_A JOIN A
      ON A.A_id = B_has_A.A_id)
    ON (B.B_id = B_has_A.B_id))
  ON (C.B_id = B.B_id)
JOIN (E JOIN E_has_C)
  ON (E.E_id = E_has_C.E_id AND C.C_id = E_has_C.C_id)
  WHERE E.E_id IN (2,3)

UNION ALL

SELECT DISTINCT B.module, B.controller, B.action, B.object_only, B.description, privileges.object_id, A.A_id
  FROM C JOIN(
    B
    LEFT JOIN (
      B_has_A JOIN A
      ON A.A_id = B_has_A.A_id)
    ON (B.B_id = B_has_A.B_id))
  ON (C.B_id = B.B_id)
JOIN (D JOIN D_has_C)
  ON (D.D_id = D_has_C.D_id AND C.C_id = D_has_C.C_id)
  WHERE D.D_id IN (1, 2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...