Можно ли объединить операторы SQL IN () более эффективным образом? - PullRequest
0 голосов
/ 04 августа 2020

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

  1. сделали заказ в любое время, И
  2. зарегистрировались session_index=1 , И
  3. зарегистрировал session_index=2

в выборочном наборе данных.

SELECT SUM(a.page_views)
FROM sessions a
WHERE a.id IN (
    SELECT b.id 
    FROM sessions b 
    WHERE b.order_id NOTNULL
        /*lookup for visitors who have made a purchase*/
)
AND a.id IN (
    SELECT c.id 
    FROM sessions c 
    WHERE c.session_index = 1
        /*lookup for visitors who have logged session_index #1*/
)
AND a.id IN (
    SELECT d.id
    FROM sessions d
    WHERE d.session_index = 2
        /*lookup for visitors who have logged session_index #2*/
)
AND a.session_index < 3;
    /*makes the SELECT SUM() add records with index #1 and #2.

Он имеет довольно ужасную эффективность, потому что он выполняет сравнение поиска три раза отдельно . Есть ли более эффективный способ создания таблицы поиска, которая объединяет три критерия таблицы поиска в один?

Ответы [ 2 ]

0 голосов
/ 04 августа 2020

Я бы предложил два уровня агрегирования:

SELECT SUM(page_views)
FROM (SELECT s.id, SUM(s.page_views) as page_views
      FROM sessions s
      WHERE s.session_index < 3
      GROUP BY s.id
      HAVING CCOUNT(s.order_id) > 0 AND  -- users have made a purchase
             SUM(CASE WHEN s.session_index = 1 THEN 1 ELSE 0 END) > 0 AND
             SUM(CASE WHEN s.session_index = 2 THEN 1 ELSE 0 END) > 0
    ) s;

Тем не менее, ваша исходная версия с правильными индексами и использованием EXISTS может быть самым быстрым методом:

SELECT SUM(s.page_views)
FROM sessions s
WHERE a.session_index < 3 AND
      EXISTS (SELECT 1
              FROM sessions s2 
              WHERE s2.id = s.id AND s2.order_id NOT NULL
             ) AND
      EXISTS (SELECT 1
              FROM sessions s2 
              WHERE s2.id = s.id AND s2.session_index = 1
             ) AND
      EXISTS (SELECT 1
              FROM sessions s2 
              WHERE s2.id = s.id AND s2.session_index = 2
             ) ;

И нужный вам индекс находится на sessions(id, session_index, order_id).

0 голосов
/ 04 августа 2020

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

SELECT id
FROM sessions
GROUP BY id
HAVING COUNT(order_id) AND SUM(session_index = 1) AND SUM(session_index = 2)

Вы можете использовать его с оператором IN для суммирования просмотров страниц:

SELECT SUM(page_views)
FROM sessions
WHERE session_index < 3
AND id IN (
    SELECT id
    FROM sessions
    GROUP BY id
    HAVING COUNT(order_id) AND SUM(session_index = 1) AND SUM(session_index = 2)
)

Или вы можете сделать это с помощью оконной функции SUM():

SELECT SUM(SUM(CASE WHEN session_index IN (1, 2) THEN page_views END)) OVER ()
FROM sessions
GROUP BY id
HAVING COUNT(order_id) AND SUM(session_index = 1) AND SUM(session_index = 2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...