SQL Server: подсчитывать появление каждого элемента в результатах выбора

Я использую простую хранимую процедуру для извлечения некоторых данных из базы данных, которая до сих пор работает нормально.

Есть ли способ в SQL, с помощью которого я могу подсчитать, как часто каждый элемент появляется в результатах моего выбора, а затем удалить дубликаты, например. глядя на столбец "url"? В основном я хочу добавить в каждую строку моих результатов выбора, а затем в идеале удалить дубликаты.

Пример. Моим нефильтрованным результатом будет: url1, url1, url1, url2, url2, url3. Вместо этого я хотел бы видеть следующее: url1 3 url2 2 url3 1

Моя хранимая процедура:

**ALTER PROCEDURE [dbo].[CountQueue]
AS
BEGIN
SET NOCOUNT ON;
SELECT      dateEsc,
            url,
            EID
FROM        QueueLog
WHERE       logStatus = 'New'
AND         region = 'US'
AND         (
                flag = 'flag1' 
                OR 
                flag = 'flag2'
            )
ORDER BY    dateEsc desc, EID desc
END**

Большое спасибо за любую помощь с этим Тимом


person user2571510    schedule 01.03.2014    source источник
comment
Основываясь на том, что вы описываете, я не понимаю, почему SELECT DISTINCT не сработает, но я подозреваю, что вы упускаете детали в своем вопросе, которые демонстрируют, почему этого недостаточно.   -  person K Richard    schedule 01.03.2014


Ответы (1)


Вы можете сделать это в запросе, вам не нужно использовать хранимую процедуру. Если я вас правильно понял, вы можете использовать "группировать по" для решения проблемы.

SELECT      url,
            count(*)
FROM        QueueLog
WHERE       logStatus = 'New'
AND         region = 'US'
AND         (
            flag = 'flag1' 
            OR 
            flag = 'flag2'
            )
GROUP BY url;

Если вы хотите получить только те URL-адреса, которые имеют дубликаты, вы можете добавить наличие:

SELECT      url,
            count(*)
FROM        QueueLog
WHERE       logStatus = 'New'
AND         region = 'US'
AND         (
            flag = 'flag1' 
            OR 
            flag = 'flag2'
            )
GROUP BY url
HAVING count(*) > 1;

Мой любимый способ удаления дубликатов — использование оконных функций. В любом случае, чтобы удалить дубликаты, вы должны знать, какой дубликат вы хотите удалить. Я предполагаю, что вы хотите удалить тот, у которого более новый dateEsc. Этот запрос здесь (или что-то подобное) должен дать вам все повторяющиеся строки. После того, как вы убедились, что они верны, нетрудно изменить выбор с удаления на удаление.

SELECT * FROM 
(
SELECT      EID,
            dateEsc,
            url,
            rank() OVER(PARTITION BY url ORDER BY dateEsc) as rank
FROM        QueueLog
WHERE       logStatus = 'New'
AND         region = 'US'
AND         (
            flag = 'flag1' 
            OR 
            flag = 'flag2'
            )
) a
WHERE a.rank > 1;

По сути, внутренний запрос берет все строки с одним и тем же URL-адресом и присваивает им ранг на основе dateEsc. Таким образом, тот, у которого самая старая датаEsc, получит «1» в столбце рангов, следующий по старшинству получит ранг 2 и так далее. Затем мы знаем, что хотим оставить объект с рангом 1 — дубликаты будут иметь ранг 2 или выше. Поэтому мы выбираем эти строки во внешнем запросе. Если вы хотите, чтобы запись была «правильной», просто измените rank() OVER(PARTITION BY url ORDER BY dateEsc) as rank на rank() OVER(PARTITION BY url ORDER BY EID) as rank или что-то подобное.

person Denise    schedule 01.03.2014
comment
Большое спасибо - это здорово, и объяснения очень помогают! - person user2571510; 01.03.2014