У меня есть транзакционные данные о покупках клиентов. Я попытался выбрать customer_id за последний 1 месяц и рассчитать давность по среднему дню, когда клиенты приходят к покупке (AVG (разрыв))
SELECT
customer_id,
(
CASE WHEN day::DATE<= '2015-05-01'::DATE AND day::DATE > '2015-05-01'::DATE - INTERVAL '1 month'
THEN
(
SELECT
AVG(gap)
FROM
(
SELECT
customer_id,
( day- LAG(day) OVER ( PARTITION BY customer_id ORDER BY day ) ) AS gap
FROM
baskets
JOIN
basket_lines
USING
( basket_id )
GROUP BY 1
) a
) b
ELSE 0
) AS A
FROM
baskets
JOIN
basket_lines
USING
(basket_id)
GROUP BY
1;
Однако у меня есть ошибка типа `
ERROR: syntax error at or near "b"
LINE 45: GROUP BY 1)a)b ELSE 0) AS A
^
Означает ли это, что я не могу использовать подзапрос после оператора THEN?
Пожалуйста, опубликуйте свои определения таблиц и некоторые образцы данных.
Кажется странным, что ваш подзапрос не связан с вашим основным запросом. Затем в самом внутреннем запросе вы группируете по customer_id, но все же пытаетесь получить доступ к столбцу day. Либо существует только одна запись на customer_id, тогда вам не нужно группировать по ней, либо это не так, тогда вам понадобится агрегатная функция на day, чтобы сообщить СУБД, какой день из дней клиента вы имеете в виду.
В какой таблице находится customer_id? В какой таблице находится day?
Ваш запрос слишком сложен. Задайте вопрос Другой. Предоставьте образцы данных, желаемый результат и лучшее объяснение того, чего вы хотите достичь.


Подзапрос в предложении THEN не принимает псевдоним. Кроме того, вы должны завершить экспрессию CASE с помощью END:
SELECT
customer_id,
(CASE WHEN day::DATE<= '2015-05-01'::DATE AND
day::DATE > '2015-05-01'::DATE - INTERVAL '1 month'
THEN
(SELECT AVG(gap) FROM (
SELECT customer_id,
(day- LAG(day) OVER (PARTITION BY customer_id ORDER BY day)) as gap
FROM baskets
JOIN basket_lines
USING (basket_id)
GROUP BY 1) a) ELSE 0 END) AS A
FROM baskets
JOIN basket_lines
USING (basket_id)
GROUP BY 1;
Но у вас есть коррелированный подзапрос в вашем операторе select. Это, вероятно, не оптимально, и мы, вероятно, сможем переписать ваш запрос, используя соединение.
Предлагаю следующий рефакторинг:
WITH cte AS (
SELECT
customer_id,
(day- LAG(day) OVER (PARTITION BY customer_id ORDER BY day)) as gap
FROM baskets
INNER JOIN basket_lines
USING (basket_id)
WHERE day::DATE<= '2015-05-01'::DATE AND
day::DATE > '2015-05-01'::DATE - INTERVAL '1 month'
)
SELECT
customer_id,
AVG(gap) AS cust_avg
FROM cte
GROUP BY
customer_id;
Подзапрос Homesand, похоже, вообще не коррелирован, но, скорее всего, это ошибка :-)
@ThorstenKettner Да ... Я тоже это видел. Я предложил рефакторинг, который может быть улучшением.
Вашему оператору
CASE WHENнуженEND, чтобы завершить его послеELSE. Обратите внимание, что использование подзапросов внутриSELECT, как правило, является плохой практикой. Я также рекомендую всегда указывать псевдонимы сAS, чтобы избежать загадочного синтаксического супа вродеBY 1) a) ELSE 0 END) AS A.