Альтернатива SELECT .. IN (..) - PullRequest
1 голос
/ 19 марта 2011

У меня есть таблица с 3 столбцами: идентификатор (человека), город (который посетил человек) и дата (его посещения). Мне нужно выбрать всех людей (их идентификаторы), которые были в городе Лос-Анджелес между конкретными датами, которые также были в городе Нью-Йорк в какую-то другую конкретную дату.

Вот пример запроса, который я выполняю сейчас:

SELECT DISTINCT id 
FROM places 
WHERE date >= '2011-03-18' AND 
      date < '2011-03-19' AND 
      city = 'los angeles' AND 
      id IN (SELECT DISTINCT id 
             FROM places 
             WHERE date >= '2011-03-15' AND 
                   date < '2011-03-16' AND 
                   city = 'chicago' 
             GROUP BY id);

Что-нибудь, что я тоже могу? Есть ли другой запрос, который я могу использовать? Этот выбор слишком медленный.

Ответы [ 4 ]

8 голосов
/ 19 марта 2011

Использование соединения (с псевдонимом) вместо подзапроса должно работать лучше:

  SELECT places.id 
    FROM places 
         JOIN places AS places2 ON places2.id = places.id
     AND places2.date >= '2011-03-15' 
     AND places2.date < '2011-03-16' 
     AND places2.city = 'chicago' 
   WHERE places.date >= '2011-03-18' 
     AND places.date < '2011-03-19' 
     AND places.city = 'los angeles' 
GROUP BY places.id;
2 голосов
/ 19 марта 2011

Сначала вы должны убедиться, что у вас есть соответствующие индексы на месте. В этом случае это, вероятно, один индекс с двумя столбцами даты и города. После этого вы можете взять ваш запрос и сравнить производительность с запросами, предложенными здесь. Внутреннее соединение может быть быстрее, чем то, что вы уже получили.

Моя версия работает в SQL Server. Я мог бы работать и в других СУБД.

select id 
from places 
where [date] >= '2011-03-18' AND 
      [date] < '2011-03-19' AND 
      city = 'los angeles'
intersect       
select id 
from places 
where [date] >= '2011-03-15' AND 
      [date] < '2011-03-16' AND 
      city = 'chicago';
1 голос
/ 19 марта 2011

Попробуйте внутреннее соединение

SELECT DISTINCT p1.id 
FROM places p1
INNER JOIN places p2 ON p1.id = p2.id AND
      p2.date >= '2011-03-18' AND 
      p2.date < '2011-03-19' AND 
      p2.city = 'los angeles'
WHERE p1.date >= '2011-03-18' AND 
      p1.date < '2011-03-19' AND 
      p1.city = 'los angeles' AND 

Проверьте индексы в таблице и посмотрите, есть ли у вас данные по городу и дате.

1 голос
/ 19 марта 2011
SELECT id
FROM places AS p1
INNER JOIN AS p2 ON p1.id = p2.id AND p2.date >= '2011-03-15' AND p2.date < '2011-03-19'
   AND p2.city = 'chicago'
WHERE p1.date >= '2011-03-18' AND p1.date < '2011-03-19' AND p1.city = 'los angelis'
...