SQL查询根据条件逻辑获得每组一行

时间:2019-01-04 20:17:46

标签: sql sql-server

我有一个表,其中的一列中有重复的值。我正在尝试根据下面描述的某些逻辑消除具有重复条目的行。

这是表格示例-

RecoveryKey   DateTime      Duration CallDisposition NewTransaction Variable8   CallTypeID
7994113912466 12/4/18 16:26 19       52              Y              152643-5657     -1    
7994113912470 12/4/18 16:26 1168     29              Y              152643-5657   6390
7994113912751 12/4/18 16:51 2686     13              N              152643-5657   6390
7994113912756 12/4/18 13:51 56       2               Y              152643-5658   6390
7994113912756 12/4/18 13:52 125      13              Y              152643-5658   6390
7994113912756 12/4/18 13:55 125      13              N              152643-5658   6390

Variable8列的前3个记录和后3个记录都有重复的值。

我想做的是,如果CallDisposition为29,而其后的下一个条目的NewTransaction值为“ N”,那么我必须将行保留为CallDisposition = 29。

对于其他所有实例,无论值CallDisposition还是NewTransaction,我都希望选择最新的行。

所以我的最终结果应该是这样

RecoveryKey   DateTime      Duration CallDisposition NewTransaction Variable8   CallTypeID
7994113912470 12/4/18 16:26 1168     29              Y              152643-5657   6390
7994113912756 12/4/18 13:55 125      13              N              152643-5658   6390

2 个答案:

答案 0 :(得分:2)

您可以使用窗口功能。假设“ 29”始终是倒数第二个记录,则可以执行以下操作:

select t.*
from (select t.*,
             row_number() over (partition by variable8 order by datetime desc) as seqnum,
             lag(CallDisposition) over (partition by variable8 order by datetime asc) as prev_CallDisposition
      from t
     ) t
where ( prev_CallDisposition = 29 and newTransaction = 'N' and seqnum = 2)  or
      ( prev_CallDisposition <> 29 or prev_CallDisposition is null or newTransaction <> 'N' and seqnum = 1 );

使用窗口函数,假设29调用可以在任何地方都比较棘手:

select t.*
from (select t.*,
             sum(case when CallDisposition = 29 and next_newTransaction = 'N' then 1 else 0 end) over (partition by variable8) as num_matching_29
      from (select t.*,
                   row_number() over (partition by variable8 order by datetime desc) as seqnum,
                   lead(newTransaction) over (partition by variable8 order by datetime asc) as next_newTransaction
            from t
           ) t
     ) t
where (CallDisposition = 29 and next_newTransaction = 'N') or
      (num_matching_29 = 0 and seqnum = 1);

答案 1 :(得分:0)

我假设有一定顺序,所以可以随意添加一个序列。这将在数​​据中的任何位置拾取29 / N组合。

DECLARE @T TABLE (datetime INT , CallDiusposition INT, NewTransaction NVARCHAR(10), Variable8 NVARCHAR(50))
INSERT @T VALUES(1,52,'Y',5657),(2,29,'Y',5657),(3,13,'N',5657),(4,2,'Y',5658),(5,13,'Y',5658),(6,13,'N',5658)

;WITH A AS
(
    SELECT *,
        RN = CASE WHEN LEAD(NewTransaction) OVER (PARTITION BY Variable8 ORDER BY datetime) ='N' AND CallDiusposition=29  THEN -1 ELSE ROW_NUMBER() OVER (PARTITION BY Variable8 ORDER BY datetime) END
    FROM @T
),
B AS
(
    SELECT Match=ROW_NUMBER() OVER (PARTITION BY Variable8 ORDER BY RN ASC),* FROM A 
)
SELECT * FROM B WHERE Match=1

没有CTE

SELECT * FROM
(
    SELECT Match=ROW_NUMBER() OVER (PARTITION BY Variable8 ORDER BY RN ASC),* FROM
    (
        SELECT *,
            RN = CASE WHEN LEAD(NewTransaction) OVER (PARTITION BY Variable8 ORDER BY datetime) ='N' AND CallDiusposition=29  THEN -1 ELSE ROW_NUMBER() OVER (PARTITION BY Variable8 ORDER BY datetime) END
        FROM @T
    )AS A
)AS B
WHERE Match=1