【问题标题】:Calculate and find the second day of the week in SQL在 SQL 中计算并找到一周的第二天
【发布时间】:2022-11-10 11:22:26
【问题描述】:

假设我有这样的数据

CustomerID Trans_date
C001 01-sep-22
C001 04-sep-22
C001 14-sep-22
C002 03-sep-22
C002 01-sep-22
C002 18-sep-22
C002 20-sep-22
C003 02-sep-22
C003 28-sep-22
C004 08-sep-22
C004 18-sep-22

但我无法根据 Trans_date 找到第一笔和第二笔交易。 我希望结果看起来像这样:

CustomerID Trans_week first second
C001 35 35 37
C001 35 35 37
C001 37 35 37
C002 35 35 37
C002 35 35 37
C002 37 35 37
C002 38 35 37
C003 35 35 39
C003 39 35 39
C004 36 36 37
C004 37 36 37

最后的结果将显示如下:

CustomerID first second
C001 35 37
C002 35 37
C003 35 39

C004 不包括在内,因为我需要在第一周获得第一名的客户 ID。

【问题讨论】:

  • 您能否分享示例输出?并请更正数据库标签。
  • 嗨,我刚刚更新了我的问题,并将我的示例结果放入。谢谢你
  • 根据问题指南,请不要发布代码、数据、错误消息等的图像 - 将文本复制或键入问题中。请保留将图像用于图表或演示渲染错误,无法通过文本准确描述的事情。
  • MySQL <> SQL Server - 请更正您的标签。
  • 没有错误,我只是不知道如何计算

标签: sql database sqlite


【解决方案1】:

您可以在子查询中使用ROW_NUMBER() 函数来获取客户的第一个和第二个交易日期,然后对该子查询的结果使用条件MAX 窗口函数。

SELECT CustomerID, DATEPART(week,CustTrans) AS Trans_week,
       DATEPART(week, MAX(CASE rn WHEN 1 THEN CustTrans END) OVER (PARTITION BY CustomerID)) first,
       DATEPART(week, MAX(CASE rn WHEN 2 THEN CustTrans END) OVER (PARTITION BY CustomerID)) second
FROM
  (
    SELECT *,
      ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY CustTrans) rn
    FROM trydata
  ) T
ORDER BY CustomerID, Trans_week

请参阅 SQL Server 上的 demo

正如您在 cmets 中所要求的,如果您只想为每个客户选择显示第一周和第二周的一行,请使用以下查询:

SELECT CustomerID,
   DATEPART(week, MAX(CASE rn WHEN 1 THEN CustTrans END)) first,
   DATEPART(week, MAX(CASE rn WHEN 2 THEN CustTrans END)) second
FROM
  (
    SELECT *,
      ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY CustTrans) rn
    FROM trydata
  ) T
WHERE rn <= 2
GROUP BY CustomerID
ORDER BY CustomerID

请参阅demo

【讨论】:

  • 如果我只想显示 1 个数据,可以吗?前任。如果 c001 在第 37 周的第 2 周显示,那么我希望它仅显示 c001 第 37 周(没有重复或显示另一周)。它不仅适用于 c001,而且适用于所有 custID
  • 你的意思是选择第二周= 37的所有行吗? check this query
  • 不。就像 C001|第 36 周|第 37 周,C002|第 36 周|第 37 周,C003|第 36 周|第 40 周,C004|第 36 周|第 39 周.....所以它只显示了一个数据,它们显示了第一周和第二周
  • 好的,我据此更新了答案,您可以检查一下。
  • @Ahmed 很干净。好方法
【解决方案2】:
with cte (RN,CustomerID, FirstWeek,SecondWeek ) as
( SELECT ROW_NUMBER() over(partition by CustomerID  ORDER BY CustomerID  )  RN, CustomerID,FirstWeek, isnull((select TOP 1 (DATEPART(week,CustTrans))   
                from trydata c 
                    where c.CustomerID = SRC.CustomerID AND DATEPART(week,C.CustTrans) > SRC.FirstWeek  
                    ORDER BY DATEPART(week,C.CustTrans) ),'0')  AS SecondWeek 
FROM (  
    SELECT CustomerID,DATEPART(week,CustTrans) TransWeek,
      (select MIN(DATEPART(week,CustTrans)) from trydata c where c.CustomerID = trydata.CustomerID) AS FirstWeek
    FROM trydata
) SRC )

select CustomerID,FirstWeek,SecondWeek from cte where RN = 1 

输出:

示例 2:

WITH CTE (CustomerID,FIrstWeek,RN) AS (
    SELECT CustomerID,MIN(DATEPART(week,CustTrans)) TransWeek,
    ROW_NUMBER() over(partition by CustomerID  ORDER BY DATEPART(week,CustTrans) asc ) FROM TryData 
    GROUP BY CustomerID,DATEPART(week,CustTrans)
) 

SELECT CTE.CustomerID, CTE.FIrstWeek,  
     (select TOP 1 (DATEPART(week,c.CustTrans))   
        from trydata c 
            where c.CustomerID = CTE.CustomerID AND DATEPART(week,C.CustTrans) > CTE.FIrstWeek 
                )   SecondWeek 
FROM CTE  
WHERE RN = 1

FIddle Demo

编辑:这可以通过更简单的方式完成,并且不太复杂。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多