MySQL кросс присоединиться не в? - PullRequest
0 голосов
/ 25 октября 2009

Используя запрос, подобный приведенному ниже, вы можете выбрать строки, в которых цвет идентификатора - синий, фиолетовый, зеленый, белый и черный.

SELECT t1.id, col
FROM extra as e INNER JOIN your_table as t1 USING ( id )
CROSS JOIN your_table as t2 USING ( id )
CROSS JOIN your_table as t3 USING ( id )
CROSS JOIN your_table as t4 USING ( id )
CROSS JOIN your_table as t5 USING ( id )
WHERE t1.color = 'blue' and t2.color = 'purple' and t3.color= 'green' and t4.color= 'white' and t5.color= 'black'

Если вы попытаетесь использовать! = Или NOT IN, это не сработает. Как мне написать запрос, чтобы цвета содержали синий, фиолетовый, зеленый, белый, но НЕ черный?

Ответы [ 3 ]

2 голосов
/ 25 октября 2009

Я не знаю, почему вы используете CROSS JOIN. Это обычно для создания декартовых продуктов. Все, что вам нужно, это просто INNER JOIN или просто JOIN.

Я обычно использую OUTER JOIN, когда хочу проверить отсутствие некоторых данных. Если совпадений не найдено, t5 будет НЕДЕЙСТВИТЕЛЕН.

SELECT t1.id, col
FROM extra as e 
INNER JOIN your_table as t1 ON ( e.id=t1.id AND t1.color = 'blue' )
INNER JOIN your_table as t2 ON ( e.id=t2.id AND t2.color = 'purple' )
INNER JOIN your_table as t3 ON ( e.id=t3.id AND t3.color = 'green' )
INNER JOIN your_table as t4 ON ( e.id=t4.id AND t4.color = 'white' )
LEFT OUTER JOIN your_table as t5 ON ( e.id=t5.id AND t5.color = 'black' )
WHERE t5.id IS NULL;

Вы правы, что вышеуказанная техника с использованием объединений быстрее, чем с помощью коррелированных подзапросов, и также (по крайней мере, в MySQL) быстрее, чем решение GROUP BY, которое используют некоторые люди:

SELECT e.id, col
FROM extra as e
INNER JOIN your_table AS t USING ( id)
WHERE t.color IN ('blue', 'purple', 'green', 'white')
GROUP BY e.id
HAVING COUNT(*) = 4;

(Этот запрос не решает проблему «не черных», я просто иллюстрирую технику.)

2 голосов
/ 25 октября 2009

Вы можете сделать что-то вроде:

select e.id
from   extra as e
where  exists (select null from your_table as t where t.id = e.id and t.color = 'blue')
  and  exists (select null from your_table as t where t.id = e.id and t.color = 'purple')
  and  exists (select null from your_table as t where t.id = e.id and t.color = 'green')
  and  exists (select null from your_table as t where t.id = e.id and t.color = 'white')
  and not exists (select null from your_table as t where t.id = e.id and t.color = 'black')

Или что-то вроде этого, вероятно, будет более эффективным:

select e.id
from   extra as e
where  4 = 
       (select count(*) 
        from   your_table as t 
        where  t.id = e.id 
          and  t.color in ('blue', 'purple', 'green', 'white'))
  and  0 = 
       (select count(*) 
        from   your_table as t 
        where  t.id = e.id 
          and  t.color in ('black'))
0 голосов
/ 25 октября 2009

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

select * from cars join colors where cars.colorid = colors.colorid where colors.color != 'black'
...