2015-12-07 4 views
1

У меня есть следующий SQL, который работает, чтобы найти дубликатыSQL Server 2008 - Поиск дубликатов с использованием ROW_NUMBER

SELECT * 
FROM (SELECT 
     id, 
     ShipAddress, 
     ShipZIPPostal, 
     ROW_NUMBER() OVER (PARTITION BY shipaddress, shipzippostal ORDER BY shipaddress) ROWNUM 
FROM orders 
WHERE CONVERT(date, orderdate) = CONVERT(date, GETDATE())) x 
WHERE rownum > 1 

Я хотел бы видеть только строки, в которых, если значение RowNum> 1, то я хотел бы видеть его соответствующая строка, где rownum = 1.

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

Если строка не имеет дубликатов, то я не хочу видеть его (он будет иметь ROWNUM = 1)

Как бы я это сделать, пожалуйста?

веселит

ответ

2

Использование count(*) вместо row_number():

SELECT * 
FROM (SELECT id, ShipAddress, ShipZIPPostal, 
      COUNT(*) OVER (PARTITION BY shipaddress, shipzippostal) as cnt 
     FROM orders 
     WHERE CONVERT(date, orderdate) = CONVERT(date, GETDATE()) 
    ) x 
WHERE cnt > 1; 
0

В дополнение к ответу Гордона, если вы хотите сохранить подход row_number() для какой-то академической причине, вы можете сделать это:

SELECT * 
FROM (SELECT 
     id, 
     ShipAddress, 
     ShipZIPPostal, 
     ROW_NUMBER() OVER (PARTITION BY shipaddress, shipzippostal ORDER BY shipaddress) ROWNUM 
FROM orders 
WHERE CONVERT(date, orderdate) = CONVERT(date, GETDATE())) x 
WHERE EXISTS(
SELECT * FROM x x2 
WHERE x.shipaddress=x2.shipaddress 
AND x.shipzippostal=x2.shipzippostal 
AND x2.ROWNUM>1 
) 

Я бы предпочел такую ​​структуру, как это лично:

WITH cte AS (
    SELECT 
     id, 
     ShipAddress, 
     ShipZIPPostal, 
     ROW_NUMBER() OVER (PARTITION BY shipaddress, shipzippostal ORDER BY shipaddress) ROWNUM 
    FROM orders 
    WHERE CONVERT(date, orderdate) = CONVERT(date, GETDATE()) 
) 
SELECT * 
FROM cte 
WHERE EXISTS(
SELECT * FROM cte x2 
WHERE cte.shipaddress=x2.shipaddress 
AND cte.shipzippostal=x2.shipzippostal 
AND x2.ROWNUM>1 
) 
+0

Ваш первый подход не будет работать, в 'x' в 'where exists' не определен. Я согласен, что CTE - это более чистое решение (если требуется 'row_number') – HoneyBadger

+0

Ну в первом подходе' x' является псевдонимом производной таблицы в основном запросе. Я не тестировал, но я думаю, что функция EXISTS() будет иметь к ней доступ. При использовании подхода CTE это обязательно должно работать. –

+0

Нет, он не работает, он работает только в предложении 'where', где вы связываете условие where с основным запросом. Вам нужно будет переписать определение таблицы 'x' для выбора из' exist'. Вот почему CTE намного лучше. – HoneyBadger

0

Вы можете добавить второй row_number, но изменить заказ на ID, так что будет по-другому, и сравнить 2 row_numbers

SELECT 
    * 
FROM 
    (SELECT 
     id, 
     ShipAddress, 
     ShipZIPPostal, 
     ROW_NUMBER() OVER (PARTITION BY shipaddress,shipzippostal ORDER BY id) ROWNUM1, 
     ROW_NUMBER() OVER (PARTITION BY shipaddress,shipzippostal ORDER BY id DESC) ROWNUM2 
    FROM 
     orders 
    WHERE 
     CONVERT(DATE,orderdate) = CONVERT(DATE,GETDATE()) 
    ) x 
WHERE 
    ROWNUM1 <> ROWNUM2 
Смежные вопросы