Считайте различные значения с помощью OVER (PARTITION BY id)

Можно ли считать различные значения в сочетании с функциями окна, такими как OVER(PARTITION BY id)? В настоящее время мой запрос выглядит следующим образом:

SELECT congestion.date, congestion.week_nb, congestion.id_congestion,
   congestion.id_element,
ROW_NUMBER() OVER(
    PARTITION BY congestion.id_element
    ORDER BY congestion.date),
COUNT(DISTINCT congestion.week_nb) OVER(
    PARTITION BY congestion.id_element
) AS week_count
FROM congestion
WHERE congestion.date >= '2014.01.01'
AND congestion.date <= '2014.12.31'
ORDER BY id_element, date

Однако, когда я пытаюсь выполнить запрос, я получаю следующую ошибку:

"COUNT(DISTINCT": "DISTINCT is not implemented for window functions"

Ответ 1

Нет, как указано в сообщении об ошибке, DISTINCT не выполняется с функциями Windows. Отправляя информацию из эту ссылку в ваше дело, вы можете использовать что-то вроде:

WITH uniques AS (
 SELECT congestion.id_element, COUNT(DISTINCT congestion.week_nb) AS unique_references
 FROM congestion
WHERE congestion.date >= '2014.01.01'
AND congestion.date <= '2014.12.31'
 GROUP BY congestion.id_element
)

SELECT congestion.date, congestion.week_nb, congestion.id_congestion,
   congestion.id_element,
ROW_NUMBER() OVER(
    PARTITION BY congestion.id_element
    ORDER BY congestion.date),
uniques.unique_references AS week_count
FROM congestion
JOIN uniques USING (id_element)
WHERE congestion.date >= '2014.01.01'
AND congestion.date <= '2014.12.31'
ORDER BY id_element, date

В зависимости от ситуации вы также можете поместить подзапрос прямо в SELECT -list:

SELECT congestion.date, congestion.week_nb, congestion.id_congestion,
   congestion.id_element,
ROW_NUMBER() OVER(
    PARTITION BY congestion.id_element
    ORDER BY congestion.date),
(SELECT COUNT(DISTINCT dist_con.week_nb)
    FROM congestion AS dist_con
    WHERE dist_con.date >= '2014.01.01'
    AND dist_con.date <= '2014.12.31'
    AND dist_con.id_element = congestion.id_element) AS week_count
FROM congestion
WHERE congestion.date >= '2014.01.01'
AND congestion.date <= '2014.12.31'
ORDER BY id_element, date

Ответ 2

Я считаю, что самый простой способ - использовать подзапрос /CTE и условную агрегацию:

SELECT c.date, c.week_nb, c.id_congestion, c.id_element,
       ROW_NUMBER() OVER (PARTITION BY c.id_element ORDER BY c.date),
       (CASE WHEN seqnum = 1 THEN 1 ELSE 0 END) as week_count
FROM (SELECT c.*,
             ROW_NUMBER() OVER (PARTITION BY c.congestion.id_element, c.week_nb
                                ORDER BY c.date) as seqnum
      FROM congestion c
     ) c
WHERE c.date >= '2014.01.01' AND c.date <= '2014.12.31'
ORDER BY id_element, date