根据条件标记一系列交易中的所有交易

问题描述 投票:0回答:2

假设我们有以下数据,你能帮我写一个查询,用条件标记参与一系列的所有交易吗:

该系列以 RespCode = '57' 的交易开始 该系列以系列开始后 RespStatus = 'A' 的第一笔交易结束。在这期间,我们可以使用不同的 RespCode 进行交易,但 RespStatus 仍为“D”。

版本是SQL 2017。

这些是卡交易,RespStatus 是交易是被批准还是被拒绝。 RespCode 是下降的原因。

预期结果如图所示 - 我需要标记以 RespCode = '57' 开头的一系列被拒绝交易 (RespStatus = 'D') 一部分的交易。已批准的交易 (RespStatus = 'A') 结束该系列。

例如,第 20、21、22 行被标记,因为它们都被拒绝,并且该系列以 RespCode = '57' 开始。

第 24 行未标记,因为它已被拒绝,但该系列并非以 RespCode = '57' 开头。

CREATE TABLE #temptable ( [ID] int, [Datetime] datetime, Card varchar(23), [RespCode] varchar(25), [RespStatus] char(1) )
INSERT INTO #temptable
VALUES
( 11377422, N'2023-04-19T20:53:24', '111111XXXXXX1111', '00', 'A' ), 
( 11823828, N'2023-04-29T00:06:48', '111111XXXXXX1111', '00', 'A' ), 
( 12229230, N'2023-05-10T04:14:56', '111111XXXXXX1111', '00', 'A' ), 
( 12761727, N'2023-05-23T05:49:00', '111111XXXXXX1111', '00', 'A' ), 
( 12949136, N'2023-05-28T22:33:25', '111111XXXXXX1111', '00', 'A' ), 
( 13336176, N'2023-06-06T00:23:11', '111111XXXXXX1111', '00', 'A' ), 
( 13478042, N'2023-06-09T02:18:06', '111111XXXXXX1111', '00', 'A' ), 
( 13801436, N'2023-06-18T19:55:52', '111111XXXXXX1111', '00', 'A' ), 
( 14442178, N'2023-07-02T00:17:37', '111111XXXXXX1111', '00', 'A' ), 
( 14583163, N'2023-07-06T22:40:14', '111111XXXXXX1111', '00', 'A' ), 
( 14698189, N'2023-07-09T22:44:22', '111111XXXXXX1111', '00', 'A' ), 
( 15107992, N'2023-07-18T04:20:51', '111111XXXXXX1111', '00', 'A' ), 
( 16129455, N'2023-08-18T23:22:18', '111111XXXXXX1111', '57', 'D' ), 
( 16203188, N'2023-08-20T18:21:32', '111111XXXXXX1111', '57', 'D' ), 
( 16254102, N'2023-08-21T02:59:09', '111111XXXXXX1111', '51', 'D' ), 
( 16343718, N'2023-08-25T21:04:59', '111111XXXXXX1111', '57', 'D' ), 
( 4983081, N'2022-09-05T17:04:58', '111111XXXXXX1111', '00', 'A' ), 
( 5621620, N'2022-10-06T18:20:53', '111111XXXXXX1111', '00', 'A' ), 
( 5762366, N'2022-10-12T16:18:47', '111111XXXXXX1111', '00', 'A' ), 
( 5870930, N'2022-10-17T22:01:09', '111111XXXXXX1111', '00', 'A' ), 
( 6169728, N'2022-10-29T16:38:20', '111111XXXXXX1111', '00', 'A' ), 
( 6300325, N'2022-11-03T19:25:42', '111111XXXXXX1111', '57', 'D' ), 
( 6405161, N'2022-11-07T15:54:50', '111111XXXXXX1111', '00', 'A' ), 
( 6557420, N'2022-11-12T14:46:59', '111111XXXXXX1111', '00', 'A' ), 
( 6972655, N'2022-11-26T17:23:09', '111111XXXXXX1111', '57', 'D' ), 
( 7429597, N'2022-12-11T17:24:10', '111111XXXXXX1111', '00', 'A' ), 
( 7429817, N'2022-12-11T17:15:13', '111111XXXXXX1111', '54', 'D' ), 
( 7539293, N'2022-12-14T01:04:45', '111111XXXXXX1111', '00', 'A' ), 
( 7650241, N'2022-12-19T18:08:22', '111111XXXXXX1111', '57', 'D' ), 
( 8386080, N'2023-01-18T17:28:29', '111111XXXXXX1111', 'N7', 'D' ), 
( 8683916, N'2023-01-26T01:28:30', '111111XXXXXX1111', '57', 'D' ), 
( 8725093, N'2023-01-28T22:41:50', '111111XXXXXX1111', '51', 'D' ), 
( 8863541, N'2023-02-01T17:33:23', '111111XXXXXX1111', '51', 'D' ), 
( 9359202, N'2023-02-16T17:13:26', '111111XXXXXX1111', '00', 'A' ), 
( 9573895, N'2023-02-22T08:45:36', '111111XXXXXX1111', '00', 'A' ), 
( 9708832, N'2023-02-26T00:15:45', '111111XXXXXX1111', '57', 'D' ), 
( 9931305, N'2023-03-03T17:53:16', '111111XXXXXX1111', '51', 'D' ), 
( 9985985, N'2023-03-06T17:42:56', '111111XXXXXX1111', '51', 'D' ), 
( 10245315, N'2023-03-16T04:04:34', '111111XXXXXX1111', '51', 'D' ), 
( 10345800, N'2023-03-20T19:40:11', '111111XXXXXX1111', '00', 'A' ), 
( 10386960, N'2023-03-09T22:17:58', '111111XXXXXX1111', '00', 'A' ), 
( 10630165, N'2023-03-26T01:18:03', '111111XXXXXX1111', '57', 'D' ), 
( 10974576, N'2023-04-05T03:12:51', '111111XXXXXX1111', '00', 'A' ), 
( 11111336, N'2023-04-10T02:45:24', '111111XXXXXX1111', '00', 'A' )
sql sql-server gaps-and-islands
2个回答
0
投票

您想要迭代行。在 SQL 中,交互是通过递归查询完成的。两个步骤: 1. 用

ROW_NUMBER
对所有行进行编号。 2. 循环遍历各行并设置标志。

with numbered as
(
  select 
    [ID], [Datetime], Card, [RespCode], [RespStatus],
    row_number() over (order by datetime, id) as rn
  from #temptable
)
, marked as
(
  select
    [ID], [Datetime], Card, [RespCode], [RespStatus], rn,
    case when [RespCode] = '57' and [RespStatus] = 'D' then 1 else 0 end as flag
  from numbered
  where rn = 1
  union all
  select
    n.[ID], n.[Datetime], n.Card, n.[RespCode], n.[RespStatus], n.rn,
    case when n.[RespCode] = '57' and n.[RespStatus] = 'D' then 1 
         when n.[RespStatus] = 'A' then 0
         else m.flag
    end as flag
  from marked m
  join numbered n on n.rn = m.rn + 1
)
select [ID], [Datetime], Card, [RespCode], [RespStatus], flag
from marked
order by rn;

演示:https://dbfiddle.uk/byRzqUHA


0
投票

你可以这样做:

select z.*, case when respstatus <> 'A' and i = 1 then 1 else 0 end as flag
from (
  select y.*, 
    max(case when respcode = '57' then 1 else 0 end) 
    over(partition by g order by datetime) as i
  from (
    select x.*, sum(case when nrs = 'A' then 1 else 0 end)
                over(order by datetime) as g
    from (
      select t.*, lag(respstatus) over(order by datetime) as nrs
      from #temptable t
    ) x
  ) y
) z

请参阅 db<>fiddle 处的运行示例。

© www.soinside.com 2019 - 2024. All rights reserved.