如何根据第一行数据验证数据并删除无效数据

时间:2016-12-20 07:13:24

标签: sql sql-server-2012

CREATE TABLE #mappingInfo(id INT IDENTITY(1, 1), cntID INT, intCntId INT, conID INT)    
INSERT INTO #mappingInfo VALUES 
(921, 111, 30),
(921, 111, NULL),
(921, NUll, NULL),
(921, NULL, 40),
(921, 111, 50),
(922, NULL, 40),
(922, 111, 50),
(922, NULL, 60)

从上表中,列intCntIdconID是选项,但如果我们在这两列中设置计算数据,则所有其他数据应与第一列的形式相同。我的意思是第一行总是有效,如下例所示:

intCntId    conID
NULL        10

Other setup Can be 
NULL        20
NULL        30

Can't be
NULL        NULL
20          NULL
30          30

如果该列的第一个数据是NULLNOT NULL,则其余的设置数据应该相同,但可以使用不同的值进行定义。

在上表中FIRSTLAST行有效,我必须pick只有效数据或delete无效数据。

非常感谢任何帮助。

注意:我已经更新了问题,因为它是由每个cntID明智地完成的。所以我在样本表中添加了更多记录

2 个答案:

答案 0 :(得分:1)

这是一种方式(不确定最佳方式)

SELECT *
FROM   (SELECT TOP 1 WITH ties id,
                               cntID,
                               intCntId,
                               conID
        FROM   #mappingInfo
        ORDER  BY Row_number()OVER(partition BY cntID ORDER BY id)) a
UNION ALL
SELECT a.id,
       a.cntID,
       a.intCntId,
       a.conID
FROM   (SELECT *
        FROM   (SELECT CASE WHEN conID IS NULL THEN 0 ELSE 1 END conID_iden,
                       CASE WHEN intCntId IS NULL THEN 0 ELSE 1 END intCntId_iden,
                       Row_number()OVER(partition BY cntID ORDER BY id) AS rn,*
                FROM   #mappingInfo) A
        WHERE  rn <> 1) A
       JOIN (SELECT TOP 1 WITH ties CASE WHEN conID IS NULL THEN 0 ELSE 1 END AS conID_iden,
                                    CASE WHEN intCntId IS NULL THEN 0 ELSE 1 END intCntId_iden,*
             FROM   #mappingInfo
             ORDER  BY Row_number()OVER(partition BY cntID ORDER BY id)) b
         ON a.conID_iden = b.conID_iden
            AND a.intCntId_iden = b.intCntId_iden
            AND a.cntID = b.cntID 

答案 1 :(得分:1)

这是另一种方法。 cte可能需要一些额外的修改 - 例如a&#34; FIRST_VALUE OVER&#34;或者&#34; WHERE ID =(SELECT min(ID)...)&#34;。然而,相当轻的&#34;解决方案:

DECLARE @t TABLE (id INT IDENTITY(1, 1), cntID INT, intCntId INT, conID INT)    
INSERT INTO @t VALUES 
(921, 111, 30),
(921, 111, NULL),
(921, NUll, NULL),
(921, NULL, 40),
(921, 111, 50),
(922, NULL, 40),
(922, 111, 50),
(922, NULL, 60);

WITH cte AS(
  SELECT cntID
        ,CASE WHEN intCntId IS NULL THEN 0 ELSE 1 END AS intCntId
        ,CASE WHEN conID IS NULL THEN 0 ELSE 1 END AS conID
        ,ROW_NUMBER() OVER (PARTITION BY cntID ORDER BY id) AS rn
    FROM @t
)
SELECT *
  FROM @t AS t
  JOIN cte AS c
    ON t.cntID = c.cntID
    AND CASE WHEN t.intCntId IS NULL THEN 0 ELSE 1 END = c.intCntId
    AND CASE WHEN t.conID IS NULL THEN 0 ELSE 1 END = c.conID
  WHERE c.rn = 1