我下面有一个数据库表,我想从中编写一个 sql 查询来提取下面所需的输出。
ProductID RecordID ProductVersion ReceivedDate UrgencyLevel Resolved InvestigationDate ResolvedDate
1 17 1 2001-09-11 17:05:00 NULL 0 NULL NULL
1 17 10 2001-09-11 17:05:00 6 1 2001-09-11 17:59:00 2001-09-11 20:04:00
2 13 1 2001-12-04 09:05:00 6 0 NULL NULL
2 13 11 2001-12-04 09:05:00 5 1 2001-12-04 10:19:00 2001-12-04 12:07:00
3 71 1 2001-06-08 12:36:00 5 0 2001-06-08 12:36:00 NULL
3 71 6 2001-06-08 12:36:00 1 1 2001-06-08 12:36:00 2001-06-08 13:21:00
4 10 1 2001-05-01 11:00:00 1 0 2001-05-01 12:00:00 2001-05-01 12:30:00
4 10 3 2001-05-01 11:00:00 1 1 2001-05-01 12:15:00 NULL
5 21 1 2001-07-23 09:00:00 8 0 2001-07-23 10:15:00 NULL
5 21 15 2001-07-23 09:00:00 NULL 0 2001-05-23 10:30:00 NULL
每个 ProductID 都有一个 ProductVersion = 1(最低版本)和第二个 ProductVersion (最高版本)。对于每个唯一的ProductID,ReceivedDate 始终相同。此外,ReceivedDate永远不会为NULL,但ResolvedDate可以为NULL。
DurationInMinutes 在最大版本上计算为
ReceivedDate - ResolvedDate
。如果最大 ProductVersion 上的 ResolvedDate 为 NULL,则使用最小 ProductVersion 上的 ResolvedDate,否则将 NULL 分配给 DurationInMinutes。
Resolved 列在最低版本上通常为 0,在最高版本上为 1,但在某些情况下(例如,对于 ProductID 5),我们可能在两个产品版本上都具有 0 值。在这种情况下,我们希望将最大版本上的Resolved值强制为1而不是0。
ProductID RecordID ReceivedDate FirstUrgencyLevel FinalUrgencyLevel FirstInvestigationDate FinalInvestigationDate DurationInMinutes
1 17 2021-09-11 17:05:00 NULL 6 NULL 2001-09-11 17:59:00 179
2 13 2001-12-04 09:05:00 6 5 NULL 2001-12-04 10:19:00 182
3 71 2001-06-08 12:36:00 5 1 2001-06-08 12:36:00 2001-06-08 12:36:00 45
4 10 2001-05-01 11:00:00 1 1 2001-05-01 12:00:00 2001-05-01 12:15:00 90
5 21 2001-07-23 09:00:00 8 NULL 2001-07-23 10:15:00 2001-07-23 10:30:00 NULL
我已经尝试了以下方法,但似乎没有得到所需的输出。此外,我如何结合上述不同的逻辑来获得我想要的输出。
select
ProductID,
RecordID,
ReceivedDate,
case when UrgencyLevel = 0 then UrgencyLevel end as FirstUrgencyLevel,
case when UrgencyLevel = 1 then UrgencyLevel end as FinalUrgencyLevel,
case when UrgencyLevel = 0 then InvestigationDate end as FirstInvestigationDate,
case when UrgencyLevel = 1 then InvestigationDate end as FinalInvestigationDate,
datediff(minute,ReceivedDate, ResolvedDate) as DurationInMinutes
from PRODUCT
你可以
MAX(ProductVersion) OVER(PARTITION BY ProductID, RecordID)
窗口函数 识别每组输入行的最后一个 ProductVersion
。这可以包装在 CTE(公共表表达式)中。CROSS APPLY
将第一行标记为 ProductVersion = 1
,最后一行定义为 ProductVersion = MaxProductVersion
。COUNT()
、SUM()
或 MAX()
)以及条件 CASE
表达式或 IIF()
函数来选择性地在结果中包含或排除值的技术。生成的查询类似于:
WITH ProductWIthMaxVersion AS (
SELECT
*,
MAX(ProductVersion) OVER(PARTITION BY ProductID, RecordID)
AS MaxProductVersion
FROM Product
)
SELECT
PM.ProductID,
PM.RecordID,
MAX(PM.ReceivedDate) AS ReceivedDate,
MAX(CASE WHEN F.IsFirst = 1 THEN PM.UrgencyLevel END) AS FirstUrgencyLevel,
MAX(CASE WHEN F.IsFinal = 1 THEN PM.UrgencyLevel END) AS FinalUrgencyLevel,
MAX(CASE WHEN F.IsFirst = 1 THEN PM.InvestigationDate END) AS FirstInvestigationDate,
MAX(CASE WHEN F.IsFinal = 1 THEN PM.InvestigationDate END) AS FinalInvestigationDate,
MAX(CASE WHEN F.IsFinal = 1 THEN
DATEDIFF(minute, PM.ReceivedDate, PM.ResolvedDate) END) AS DurationInMinutes
FROM ProductWIthMaxVersion PM
CROSS APPLY (
SELECT
CASE WHEN PM.ProductVersion = 1 THEN 1 ELSE 0 END AS IsFirst,
CASE WHEN PM.ProductVersion = PM.MAXProductVersion THEN 1 ELSE 0 END AS IsFinal
) F
GROUP BY PM.ProductID, PM.RecordID
ORDER BY PM.ProductID, PM.RecordID
结果:
产品ID | 记录ID | 收到日期 | 第一紧急级别 | 最终紧急程度 | 首次调查日期 | 最终调查日期 | 持续时间(分钟) |
---|---|---|---|---|---|---|---|
1 | 17 | 2001-09-11 17:05:00 | 空 | 6 | 空 | 2001-09-11 17:59:00 | 179 |
2 | 13 | 2001-12-04 09:05:00 | 6 | 5 | 空 | 2001-12-04 10:19:00 | 182 |
3 | 71 | 2001-06-08 12:36:00 | 5 | 1 | 2001-06-08 12:36:00 | 2001-06-08 12:36:00 | 45 |
4 | 10 | 2001-05-01 11:00:00 | 1 | 1 | 2001-05-01 12:00:00 | 2001-05-01 12:15:00 | 空 |
5 | 21 | 2001-07-23 09:00:00 | 8 | 空 | 2001-07-23 10:15:00 | 2001-05-23 10:30:00 | 空 |
请参阅 this db<>fiddle 进行演示。