Как мне отфильтровать результаты аналитического / оконного запроса? - PullRequest
0 голосов
/ 26 августа 2009

Я пытаюсь найти дубликаты «ключей», чтобы их можно было адресовать и превращать в правильные, уникальные ключи.

Недавно я узнал, что предложение HAVING может фильтровать результаты агрегированного запроса, ориентируясь на результаты GROUP BY. Вы группируете по предполагаемому «ключу» и ИМЕЕТЕ, где число> 1, и есть ваши проблемные строки.

У меня вопрос, что эквивалентно этому для оконных функций?

Следующая таблица должна быть только атомарной по отношению к имени и месяцу, но она использует поле даты, детализированное до дня (т. Е. Может случиться, что что-то происходит дважды или более раз в месяц, когда это должно быть только ежемесячно). 1007 *

select
  event_id,
  overly_specific_date,
  count(*) over(partition by event_id, substring(convert(char(8), overly_specific_date), 0, 7))
from events_historic
order by over(partition by event_id, substring(convert(char(8), overly_specific_date), 0, 7))

против

select
  event_id,
  count(*)
from events_historic
group by event_id, substring(convert(char(8), overly_specific_date), 0, 7)
having count(*) > 1

Первый запрос хорош, потому что он показывает, что я хочу, но я бы хотел отфильтровать его. Я знаю, что мог бы сделать это в запросе большего размера или в CTE, но я ищу что-то лаконичное, например, HAVING. Во втором запросе используется HAVING, но он больше не отображает одну часть ключа, overly_specific_date.

Как мне отфильтровать второй запрос?

Ответы [ 3 ]

0 голосов
/ 26 августа 2009

Ваша проблема в том, что overly_specific_date варьируется в зависимости от группы (вы агрегируете по месячной версии даты), поэтому невозможно отобразить overly_specific_date, так как для группы не существует отдельного значения. Чтобы перечислить все оскорбительные даты, вы должны реализовать своего рода подзапрос, заданный rexem, чтобы связать группу с разными датами.

Тем не менее, дешевым хаком, который может служить вашей цели, является выбор значения MIN / MAX overly_specific_date в вашем исходном запросе, чтобы показать диапазон дат, вызывающий сбой. (Вы также можете просто записать версию месяца в операторе MIN, если это все, что вы хотели.)

0 голосов
/ 26 августа 2009

Я бы порекомендовал CTE, но поскольку вы спросили, есть хитрый способ сделать это, используя TOP (1) WITH TIES:

select top (1) with ties
  event_id,
  overly_specific_date,
  count(*) over (
    partition by event_id,
    substring(convert(char(8), overly_specific_date), 0, 7)
  ) as ct
from events_historic
order by 
  case when count(*) over (
    partition by event_id,
    substring(convert(char(8), overly_specific_date), 0, 7)
  ) > 1 then 0 else 1 end;

Это не относится ко многим другим полезным ситуациям, но я думаю, что в вашем случае это сработает.

0 голосов
/ 26 августа 2009

CTE версия:

WITH events AS (
      SELECT t.event_id,
             COUNT(*) 'num'
        FROM EVENTS_HISTORIC t
    GROUP BY e.event_id, YEAR(t.date), MONTH(t.date), DAY(t.date)
      HAVING COUNT(*) > 1)
SELECT eh.event_id,
       eh.date,
       e.num  
  FROM EVENTS_HISTORIC eh
  JOIN events e ON e.event_id = eh.event_id

Версия без CTE:

SELECT eh.event_id,
       eh.date,
       e.num  
  FROM EVENTS_HISTORIC eh
  JOIN (SELECT t.event_id,
               COUNT(*) 'num'
          FROM EVENTS_HISTORIC t
      GROUP BY e.event_id, YEAR(t.date), MONTH(t.date), DAY(t.date)
        HAVING COUNT(*) > 1) e ON e.event_id = eh.event_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...