选择包含每个组的大多数非关键信息的行

时间:2013-01-22 04:27:58

标签: sql select sql-server-2012

好的,我有一个包含一些垃圾数据的表,没有唯一的标识符列。让我举一个我正在使用的表的例子:

     A    |   B   |  C   |        D         |   E  |
  --------------------------------------------------
1.  Fiona | Smith | NULL | 2152 Cherry Lane | CA   |
2.  Fiona | Smith | NULL | NULL             | NULL |
3.  Bill  | NULL  | ACME | 2903 Center Road | WA   |
4.  Bill  | NULL  | ACME | NULL             | NULL |
5.  NULL  | NULL  | ABC  | 2300 Water St    | PA   |
6.  NULL  | NULL  | ABC  | 2300 Water St    | PA   |
7.  NULL  | NULL  | NULL | 3455 B Street    | CO   |

我需要编写一个只捕获不同行的SELECT语句。例如,取第1行和第2行。它们显然都指向同一个人,但它们只是部分重复。在这两个中,我希望在SELECT语句中包含第1行,因为它包含每列中的大多数数据。第3行和第4行也是如此。第3行是我想要包含的行。对于第5行和第6行,选择哪一个并不重要,因为它们都是精确的重复。默认情况下会包含第7行,因为它是不同的(意思是A,B和C,而不仅仅是A和B)。

以下是我的尝试:

SELECT A, B, C = MAX(D), MAX(E), 
FROM dbo.Data
GROUP BY A, B, C;

这似乎抓住了我想要的唯一行,但数据以某种方式被放入错误的列中。

2 个答案:

答案 0 :(得分:2)

WITH recordsList
AS
(
    SELECT  A, B, C, D, E,
            ROW_NUMBER() OVER (PARTITION BY A,B,C
                               ORDER BY 
                                 CASE WHEN D IS NULL 
                                      THEN 0
                                      ELSE 1 END DESC) x
   FROM table1
)
SELECT A,B,C,D,E
FROM recordsList
WHERE x = 1

答案 1 :(得分:2)

这种方法将D和E视为相等:

DECLARE @x TABLE
(
  A VARCHAR(32), 
  B VARCHAR(32), 
  C VARCHAR(32), 
  D VARCHAR(32), 
  E VARCHAR(32)
);

INSERT @x VALUES
('Fiona', 'Smith', NULL,   '2152 Cherry Lane',  'CA'),
('Fiona', 'Smith', NULL,   NULL,                NULL),
('Bill',  NULL,    'ACME', '2903 Center Road',  'WA'),
('Bill',  NULL,    'ACME', NULL,                NULL),
(NULL  ,  NULL,    'ABC',  '2300 Water St',     'PA'),
(NULL  ,  NULL,    'ABC',  '2300 Water St',     'PA'),
(NULL  ,  NULL,    NULL,   '3455 B Street',     'CO'),
('Bob',   'Barker',NULL,   NULL,                NULL),
('Bob',   'Barker',NULL,   NULL,                'NY');

;WITH x AS
(
  SELECT A,B,C,D,E, rn = ROW_NUMBER() OVER 
  (
    PARTITION BY A,B,C
    ORDER BY COALESCE(LEN(LEFT(D,1)),0) + COALESCE(LEN(LEFT(E,1)),0) DESC
  )
  FROM @x
)
SELECT A,B,C,D,E
FROM x WHERE rn = 1;