Одна и та же таблица - объединяет таблицу в двух условиях, и любое из условий иногда ложно - PullRequest
0 голосов
/ 03 марта 2019

enter image description here

Подробности:

  1. V и C - таблицы

  2. Я хочу, чтобы C присоединился к V при 2 условиях (два C названы C0 и C1).Поскольку я должен фильтровать V по столбцам дочерних таблиц C и C отдельно в одном запросе, я думаю, что объединение необходимо.

  3. V имеет много, по крайней мере, один C и Cx иногда не существует.

Из-за 3. использование внутреннего соединения с C0 и C1 иногда приводит к пустомурезультат, но я не хочу получать белую область V.

схема:

V (id)
C (id, v_id, name, type)

Query (1):

SELECT V.* 
FROM V
INNER JOIN C AS C0 ON V.id = C0.v_id WHERE C0.type = 0
INNER JOIN C AS C1 ON V.id = C1.v_id WHERE C1.type = 1
WHERE C0.name = 'word' or C1.name = 'word'
WHERE C0.name like '%wo%'

Query (2):

SELECT V.* 
FROM V
INNER JOIN C AS C0 ON V.id = C0.v_id WHERE C0.type = 0
INNER JOIN C AS C1 ON V.id = C1.v_id WHERE C1.type = 1
WHERE C0.name = 'word' or C1.name = 'word'
WHERE C1.name like '%wo%'

WHERE C0.name = 'word' or C1.name = 'word': этот пункт существует каждый раз.

WHERE Cx.name like '%wo%': этот пункт зависит от времени.

Ответы [ 4 ]

0 голосов
/ 03 марта 2019

Если вам просто нужны столбцы из v, то на ум приходит exists.

Я бы сказал так:

select v.*
from v
where exists (select 1
              from c
              where v.id = c.v_id and
                    c.type = 0
             ) or
      exists (select 1
              from c
              where v.id = c.v_id and
                    c.type = 1
             ) ;

Это может использовать индекс наc(v_id, type).

Также было бы хорошо сформулировать это следующим образом:

select v.*
from v
where exists (select 1
              from c
              where v.id = c.v_id and
                    c.type in (0, 1)
             );

Или даже:

select v.*
from v
where v.id in (select c.v_id
               from c
               where c.type in (0, 1)
              );

Ключевая идея заключается в том, что при выполнении сравнения в where предложение, вы гарантируете, что строки не могут быть дублированы.

0 голосов
/ 03 марта 2019

плохой вопрос / детали вопроса, зная лучший контекст того, что вы хотите, даже если сокращенные поля и фактические таблицы могут помочь лучше в будущем.Тем не менее, похоже, что вы хотите, это условие «IN», основанное на ЛИБО из условий с псевдонимом «C».Не видя их, вы можете посмотреть на это так (или упростить оба критерия за секунду).

select
      v.*
   from
      VTable v
         LEFT JOIN CTable C0
            on v.SomeField = C0.SomeField
         LEFT JOIN CTable C1
            on v.SomeOtherField = C1.SomeOtherField
   where
          c0.SomeField IS NOT NULL
      OR c1.SomeField IS NOT NULL

ИЛИ ... упростить с помощью одного левого соединения, объединяя оба критерия

select
      v.*
   from
      VTable v
         LEFT JOIN CTable C0
            on ( ( v.SomeField = C0.SomeField )
              OR ( v.SomeOtherField = C0.SomeOtherField ) )
   where
      c0.SomeField IS NOT NULL

Я использовал дополнительные скобки в вышеприведенном запросе на случай, если исходные условия C0 и C1 были сами по себе сложными.

Итак, то, что вы описали как белую область в таблице "V" на простом английском, это датья все из таблицы V, которая не соответствует ни условия C0 или C1.Следовательно, выполняется левое соединение, а затем ОБЕСПЕЧИВАЕТСЯ, что они ДЕЛАЮТ, проверяя, чтобы любой столбец (хотя ожидается, что ключевой столбец) явно БЫЛ НЕДЕЙСТВИТЕЛЕН (следовательно, он существует в критериях таблицы C).

0 голосов
/ 03 марта 2019

Вам не нужно присоединяться к таблице c два раза, вы можете написать свой запрос следующим образом.

select V.*
from V as V
inner join C as C on C.v_id=V.id 
where C.name='word' and C.type in(0,1)
0 голосов
/ 03 марта 2019

Хорошо ... Вы, похоже, ищете условие EXISTS с коррелированным подзапросом:

SELECT * FROM v 
WHERE EXISTS (SELECT 1 FROM c WHERE c.c0 = v.c0 OR c.c1 = v.c1)

Это вернет все записи в таблице v, для которых в таблице существует хотя бы одна записьc, который удовлетворяет либо условию c.c0 = v.c0, либо условию c.c1 = v.c1.

. В этой ситуации преимущество коррелированного подзапроса по сравнению с подходом JOIN состоит в том, что он избегает умножения записей, когда существует более одного совпадения.в таблице c.

Если вы хотите исключить записи, которые удовлетворяют любому условию, а не включать их, просто измените WHERE EXISTS на WHERE NOT EXISTS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...