代码之家  ›  专栏  ›  技术社区  ›  Ronald Wildenberg

从结果集中消除部分重复行

  •  2
  • Ronald Wildenberg  · 技术社区  · 16 年前

    我有一个查询,它返回一个与下面类似的结果集(实际上它要大得多,有数千行):

         A    | B  | C  |    D
         -----|----|----|-----
    1    NULL | d0 | d0 | NULL
    2    NULL | d0 | d1 | NULL
    3    NULL | d0 | d2 |   a0
    4      d0 | d1 | d1 | NULL
    5      d0 | d2 | d2 |   a0
    

    其中两行被认为是重复的1和2,因为A、B和D是相同的。为了消除这个,我可以用 SELECT DISTINCT A, B, D 但是我的结果集中没有得到C列。C列是第3、4和5行的必要信息。

    那么,我如何从上面的结果集得出这个结果(C4中出现的结果也可以是 NULL 而不是 d1 ):

         A    | B  | C    | D
         -----|----|------|-----
    1    NULL | d0 | NULL | NULL
    3    NULL | d0 | d2   |   a0
    4      d0 | d1 | d1   | NULL
    5      d0 | d2 | d2   |   a0
    
    5 回复  |  直到 9 年前
        1
  •  5
  •   Lieven Keersmaekers    16 年前
    DECLARE @YourTable TABLE (
      A VARCHAR(2)
      , B VARCHAR(2)
      , C VARCHAR(2)
      , D VARCHAR(2))
    
    INSERT INTO @YourTable VALUES (NULL, 'd0', 'd0', NULL)
    INSERT INTO @YourTable VALUES (NULL, 'd0', 'd1', NULL)
    INSERT INTO @YourTable VALUES (NULL, 'd0', 'd2', 'a0')
    INSERT INTO @YourTable VALUES ('d0', 'd1', 'd1', NULL)
    INSERT INTO @YourTable VALUES ('d0', 'd2', 'd2', 'a0')
    
    
    SELECT A, B, C = MIN(C), D
    FROM @YourTable
    GROUP BY A, B, D
    

    SELECT A, B, CASE WHEN MIN(C) = MAX(C) THEN MIN(C) ELSE NULL END, D
    FROM @YourTable
    GROUP BY A, B, D
    

    SELECT A, B, CASE WHEN MIN(COALESCE(C, 'dx')) = MAX(COALESCE(C, 'dx')) THEN MIN(C) ELSE NULL END, D
    FROM @YourTable
    GROUP BY A, B, D
    
        2
  •  2
  •   Community CDub    8 年前

    使用 Dense_Rank() 用A、B和D划分
    (感谢Lieven,对于临时表查询,我必须使用它来保持演示的一致性;)

    根据 MSDN ,

    行的秩是一加上出现在相关行之前的不同秩的数目。

    分区划分 A, B, C 然后按排序 A, B, C, D 对于唯一性定义为 A, B, D . 这就是过滤的地方 1 来自。

    其中denserank=1

    这是结果

    alt text

    代码如下:

    DECLARE @YourTable TABLE (
      A VARCHAR(2)
      , B VARCHAR(2)
      , C VARCHAR(2)
      , D VARCHAR(2))
    
    INSERT INTO @YourTable VALUES (NULL, 'd0', 'd0', NULL)
    INSERT INTO @YourTable VALUES (NULL, 'd0', 'd1', NULL)
    INSERT INTO @YourTable VALUES (NULL, 'd0', 'd2', 'a0')
    INSERT INTO @YourTable VALUES ('d0', 'd1', 'd1', NULL)
    INSERT INTO @YourTable VALUES ('d0', 'd2', 'd2', 'a0')
    
    ;with DistinctTable as (
        select  *, 
        DenseRank = Dense_Rank() over (Partition By A, B, D order by A, B, C, D)
        from    @YourTable
    )
    select  A, B, C, D
    from    DistinctTable
    where   DenseRank = 1
    
        3
  •  0
  •   Speedy    16 年前

    可能是子查询?

    从存在的表1中选择A、B、C、D(从表1中选择不同的A、B、D);

        4
  •  0
  •   gbn    16 年前

    在a和d中有空的事实说明了任何存在的事物。

    C上的任何最小/最大解都不能按我想的那样给您空值。否则,使用min(c)和简单的group by。

    您必须先提取唯一键(A、B、D),然后使用该键再次确定提取行,并计算出如何处理C。

    DECLARE @TheTable TABLE (
      A varchar(2) NULL,
      B varchar(2) NULL,
      C varchar(2) NULL,
      D varchar(2) NULL
    )
    
    INSERT INTO @TheTable VALUES (NULL, 'd0', 'd0', NULL)
    INSERT INTO @TheTable VALUES (NULL, 'd0', 'd1', NULL)
    INSERT INTO @TheTable VALUES (NULL, 'd0', 'd2', 'a0')
    INSERT INTO @TheTable VALUES ('d0', 'd1', 'd1', NULL)
    INSERT INTO @TheTable VALUES ('d0', 'd2', 'd2', 'a0')
    
    SELECT DISTINCT
        T.A,
        T.B,
        CASE Number WHEN 1 THEN T.C ELSE NULL END,
        T.D
    FROM
        (SELECT
            COUNT(*) AS Number,
            A, B, D
        FROM
            @TheTable
        GROUP BY
            A, B, D
        ) UQ
        JOIN
        @TheTable T ON ISNULL(T.A, '') = ISNULL(UQ.A, '') AND ISNULL(T.B, '') = ISNULL(UQ.B, '') AND ISNULL(T.D, '') = ISNULL(UQ.D, '')
    
        5
  •  0
  •   JK.    13 年前

    如果您在表中有一个唯一的ID,那么我将使用如下代码:

    SELECT A,B,C,D FROM table WHERE id IN (SELECT DISTINCT A,B,D)
    

    问题是,你总是会得到C的第一个值,而不是有值的第一个值。