消除基于Order By SQL的重复项

时间:2017-01-20 01:41:02

标签: sql sql-server tsql greatest-n-per-group

我有一个包含20多列的表格,以及300.000多行,其中我的问题的相关列如下:

column1 |column2 |column3 | date
   123  |  657   | 2222   | 20 dec
   123  |  658   | 2222   | Null
   124  |  543   | 3333   | Null
   124  |  544   | 3333   | 1 Feb
   125  |  098   | 4444   | Null
   125  |  065   | 4444   | Null 

我做了以下查询,根据需要对它们进行排序:

select * 
from table
order by column1,column2,date desc;

结果是:

column1 |column2 |column3 | date
   123  |  657   | 2222   | 20 dec
   123  |  658   | 2222   | Null
   124  |  544   | 3333   | 1 Feb
   124  |  543   | 3333   | Null
   125  |  065   | 4444   | Null
   125  |  098   | 4444   | Null 

如果日期为column1,则主要目的是删除基于not null的行重复的行。如果他们都有Null那么我就能保留一个。所以我要找的是:

column1 |column2 |column3 | date
   123  |  657   | 2222   | 20 dec
   124  |  544   | 3333   | 1 Feb
   125  |  065   | 4444   | Null

有人可以帮助我开发此查询。我希望检索其他列的 ALL ,而不仅仅是显示的那些。

我使用的是Azure SQL,基本上是SQL Server

我试过这样做:

SELECT * FROM table AS main
WHERE main.column4 IN
(SELECT sub.MinID FROM
   (SELECT column1, column3, min(column4) As MinID
    FROM table
    GROUP BY column1, column3) AS sub)
ORDER BY main.column1, main.column3;

问题在于,由于规则为min(column4),当我Not Null的{​​{1}}值小于另一个时,{@ 1}}选择column4。我尝试了NULL,但是我收到了这个错误: min(date)我猜是因为Arithmetic overflow error converting expression to data type smalldatetime值。

如何输入规则Null而另一个Not null然后选择Null

3 个答案:

答案 0 :(得分:2)

看起来像经典top-n-per-group。一种方法是使用ROW_NUMBER

WITH
CTE
AS
(
    SELECT
        column1
        ,column2
        ,column3
        ,dt
        ,ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY dt desc, column2) AS rn
    FROM tbl
)
SELECT
    column1
    ,column2
    ,column3
    ,dt
FROM CTE
WHERE rn = 1
ORDER BY
    column1
;

PARTITION BY column1表示当column1更改时,行的编号会重新开始。 ORDER BY dt desc, column2确定对行进行编号时的顺序。最后,您只需使用WHERE rn = 1选择分区的第一行。

最终结果每column1只有一行,因此向最终ORDER BY添加更多列不会改变任何内容。

答案 1 :(得分:0)

试试这个:

Select * from table t
Where (date is not null
    and not exists 
     (select * from table 
      where date is Null
         and column1 = t.Column1)) Or
   column2 = 
     (Select Max(column2) from table
      Where column1 = t.Column1)

答案 2 :(得分:0)

CTE可能是你最好的选择:

WITH CTE
AS (
    SELECT column1
        ,column2
        ,column3
        ,DATE
        ,ROW_NUMBER() OVER (
            PARTITION BY column1 ORDER BY 
                date
                ,column1
                ,column2
                ,column3 DESC
            ) AS RN
    FROM table
    )
DELETE
FROM CTE
WHERE RN <> 1

要检查您要删除的是正确的数据,最后只需将DELETE更改为SELECT *。