根据多个条件将多个状态检索到一行SQL 2008
Retrieve multiple status into one row based on multiple conditions SQL 2008
如果星期几在(星期二,星期三,星期四,星期五和星期六),我需要根据前一天+前一天最接近的状态将多个状态检索到一行中,如果查询在星期一运行它应包括来自(星期五、星期六和星期日)的+数据之前的最接近状态,如果查询在星期日运行,则它应检索+来自(星期五和星期六)的数据之前的最接近状态,并且还应包括以前的状态,而不管状态如何不在前一天的名单上。使用状态日期,基于特定状态并按 ID 分组。
这是 table 的样子:
If Runs today (Monday Sept 28)
(101, 'Submitted','07/31/2020 13:35:41'),
(101, 'Processing','07/31/2020 15:19:23'),
(101, 'Tracking', '9/26/2020 9:18:48'),
(101, 'Approved', '9/26/2020 10:16:48'),
(101, 'Received', '9/27/2020 8:16:48'),
(101, 'Closed', '9/27/2020 9:16:48'),
Output: Processing > Tracking > Approved > Received > Closed
IF Runs Friday (Sept 25)
(102, 'Complete', '8/10/2020 9:16:41'),
(102, 'Declined', '8/13/2020 9:18:48'),
(102, 'Reviewing','9/24/2020 17:59:13'),
(102, 'Testing', '9/24/2020 19:16:05'),
(102, 'Approved', '9/24/2020 21:42:56'),
Output: Declined > Reviewing > Testing > Approved
IF Runs Wedns (Sept 23)
(104, 'Approved', '6/20/2020 12:19:17'),
(104, 'Sent', '7/20/2020 12:16:17'),
(104, 'Testing', '9/22/2020 17:46:16'),
Output: Sent > Testing
IF Runs Tues (Sept 22)
(105, 'Sent', '9/21/2020 5:46:51'),
(105, NULL, '9/21/2019 9:53:53'),
Output: This row should not come up in the report since the previous status is not listed in the
category list.
IF Runs Yesterday (Sunday Sept 27)
(107, 'Approved', '9/10/2019 9:53:54'),
(107, 'Reviewing', '9/20/2019 9:53:54'),
(107, 'Started', '9/23/2019 9:53:54'),
(107, 'Approved', '9/25/2020 9:40:54'),
(107, 'Reviewing', '9/25/2020 10:50:54'),
(107, 'Received', '9/25/2020 10:53:54'),
(107, 'Tracking', '9/26/2020 9:58:54'),
(107, 'Received', '9/26/2020 10:53:54')
Output: Started > Approved > Reviewing > Received > Tracking >Received
状态类别列表:(跟踪、已批准、正在审阅、已接收、正在测试、已关闭)
条件:
1- 如果查询在(星期二、星期三、星期四、星期五和星期六)运行
然后它应该检索前一天的前一个工作日状态之前的最近状态。
2- 如果查询在星期一运行,同样的条件适用,但它应该包括来自 > 星期五 > 星期六 > 星期日之前的最近状态的数据。
3-如果查询在星期日运行,同样的条件适用,但它应该包括来自 > 星期五 > 星期六之前的最近状态的数据
工作:
WITH CTE AS (SELECT *, Row_number() over (PARTITION BY ID ORDER BY statusDate desc) RN FROM YourTable),
CTE2 as (SELECT * FROM cte WHERE StatusDate >= (CASE WHEN DATENAME(DW,StatusDate) = 'Monday' THEN dateadd(DD, -1, cast(getdate() as date) + dateadd(DD, -2, cast(getdate() as date) + dateadd(DD, -3, cast(getdate() as date) WHEN DATENAME(DW,StatusDate) = 'Sunday' THEN dateadd(DD, -1, cast(getdate() as date) + dateadd(DD, -2, cast(getdate() as date) ELSE ateadd(DD, -1, cast(getdate() as date)) and _Status in ('Tracking', 'Approved', 'Reviewing', 'Received', 'Testing', 'Closed')), CTE3 as (SELECT * FROM CTE2 UNION SELECT * FROM CTE where RN = 2 and ID in (SELECT ID FROM CTE2)) SELECT ID, left(_Status, len(_Status)-2) as _Status FROM (SELECT Distinct t1.ID,
STUFF((SELECT t2._Status + ' > '
FROM CTE3 t2
WHERE t1.ID = t2.ID
ORDER BY StatusDate
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,0,'') _Status from CTE2 t1) Z
如有任何帮助,我们将不胜感激。
谢谢!!
这似乎适用于提供的示例数据。我需要更多示例数据来测试所有可能的边缘情况。
Fiddle:http://www.sqlfiddle.com/#!18/33d76/9/0(其他人随意盗用fiddle来测试!)
- 首先,我为每条记录分配了一个行号,这样我就可以根据您的限制为那些只有 1 行深的 ID 添加行...(CTE)请注意,我们按日期降序排列每个 ID,因此首先列出最新的记录。这样,如果同一天发生变化,第 2 行仍然是集合中的一条记录,并在联合中被淘汰;但如果一天只有 1 条记录,则先前的最新记录成为第 2 行,稍后通过 CT3 包含在数据集中。
- CTE2 根据规则将数据限制为您希望看到的数据
- 记录中的 CTE3 联合只有 1 行,因此您获得优先地位。这是有效的,因为我不关心重复的原因,因为联合消除了它们。
- 最后,我们使用 CTE2 的数据集填充来自 cte3 的数据以生成组合状态
- 使用包装查询消除末尾多余的“>”,然后离开。
.
WITH CTE AS (SELECT *, Row_number() over (PARTITION BY ID ORDER BY statusDate desc) RN FROM YourTable),
CTE2 as (SELECT * FROM cte WHERE StatusDate >= dateadd(DD, -1, cast(getdate() as date))
and _Status in ('Tracking', 'Approved', 'Reviewing', 'Received', 'Testing', 'Closed')),
CTE3 as (SELECT * FROM CTE2 UNION SELECT * FROM CTE where RN = 2 and ID in (SELECT ID FROM CTE2))
SELECT ID, left(_Status, len(_Status)-2) as _Status
FROM (SELECT Distinct t1.ID,
STUFF((SELECT t2._Status + ' > '
FROM CTE3 t2
WHERE t1.ID = t2.ID
ORDER BY StatusDate
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,0,'') _Status
from CTE2 t1) Z
结果:
ID _Status
101 Processing > Tracking
102 Approved > Reviewing > Approved
107 Tracking > Received
给猫剥皮的方法有很多;这只是 1。(众所周知的猫;不想受到动物爱好者的仇恨!)
如果星期几在(星期二,星期三,星期四,星期五和星期六),我需要根据前一天+前一天最接近的状态将多个状态检索到一行中,如果查询在星期一运行它应包括来自(星期五、星期六和星期日)的+数据之前的最接近状态,如果查询在星期日运行,则它应检索+来自(星期五和星期六)的数据之前的最接近状态,并且还应包括以前的状态,而不管状态如何不在前一天的名单上。使用状态日期,基于特定状态并按 ID 分组。
这是 table 的样子:
If Runs today (Monday Sept 28)
(101, 'Submitted','07/31/2020 13:35:41'),
(101, 'Processing','07/31/2020 15:19:23'),
(101, 'Tracking', '9/26/2020 9:18:48'),
(101, 'Approved', '9/26/2020 10:16:48'),
(101, 'Received', '9/27/2020 8:16:48'),
(101, 'Closed', '9/27/2020 9:16:48'),
Output: Processing > Tracking > Approved > Received > Closed
IF Runs Friday (Sept 25)
(102, 'Complete', '8/10/2020 9:16:41'),
(102, 'Declined', '8/13/2020 9:18:48'),
(102, 'Reviewing','9/24/2020 17:59:13'),
(102, 'Testing', '9/24/2020 19:16:05'),
(102, 'Approved', '9/24/2020 21:42:56'),
Output: Declined > Reviewing > Testing > Approved
IF Runs Wedns (Sept 23)
(104, 'Approved', '6/20/2020 12:19:17'),
(104, 'Sent', '7/20/2020 12:16:17'),
(104, 'Testing', '9/22/2020 17:46:16'),
Output: Sent > Testing
IF Runs Tues (Sept 22)
(105, 'Sent', '9/21/2020 5:46:51'),
(105, NULL, '9/21/2019 9:53:53'),
Output: This row should not come up in the report since the previous status is not listed in the
category list.
IF Runs Yesterday (Sunday Sept 27)
(107, 'Approved', '9/10/2019 9:53:54'),
(107, 'Reviewing', '9/20/2019 9:53:54'),
(107, 'Started', '9/23/2019 9:53:54'),
(107, 'Approved', '9/25/2020 9:40:54'),
(107, 'Reviewing', '9/25/2020 10:50:54'),
(107, 'Received', '9/25/2020 10:53:54'),
(107, 'Tracking', '9/26/2020 9:58:54'),
(107, 'Received', '9/26/2020 10:53:54')
Output: Started > Approved > Reviewing > Received > Tracking >Received
状态类别列表:(跟踪、已批准、正在审阅、已接收、正在测试、已关闭)
条件:
1- 如果查询在(星期二、星期三、星期四、星期五和星期六)运行 然后它应该检索前一天的前一个工作日状态之前的最近状态。
2- 如果查询在星期一运行,同样的条件适用,但它应该包括来自 > 星期五 > 星期六 > 星期日之前的最近状态的数据。
3-如果查询在星期日运行,同样的条件适用,但它应该包括来自 > 星期五 > 星期六之前的最近状态的数据
工作:
WITH CTE AS (SELECT *, Row_number() over (PARTITION BY ID ORDER BY statusDate desc) RN FROM YourTable),
CTE2 as (SELECT * FROM cte WHERE StatusDate >= (CASE WHEN DATENAME(DW,StatusDate) = 'Monday' THEN dateadd(DD, -1, cast(getdate() as date) + dateadd(DD, -2, cast(getdate() as date) + dateadd(DD, -3, cast(getdate() as date) WHEN DATENAME(DW,StatusDate) = 'Sunday' THEN dateadd(DD, -1, cast(getdate() as date) + dateadd(DD, -2, cast(getdate() as date) ELSE ateadd(DD, -1, cast(getdate() as date)) and _Status in ('Tracking', 'Approved', 'Reviewing', 'Received', 'Testing', 'Closed')), CTE3 as (SELECT * FROM CTE2 UNION SELECT * FROM CTE where RN = 2 and ID in (SELECT ID FROM CTE2)) SELECT ID, left(_Status, len(_Status)-2) as _Status FROM (SELECT Distinct t1.ID,
STUFF((SELECT t2._Status + ' > '
FROM CTE3 t2
WHERE t1.ID = t2.ID
ORDER BY StatusDate
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,0,'') _Status from CTE2 t1) Z
如有任何帮助,我们将不胜感激。
谢谢!!
这似乎适用于提供的示例数据。我需要更多示例数据来测试所有可能的边缘情况。
Fiddle:http://www.sqlfiddle.com/#!18/33d76/9/0(其他人随意盗用fiddle来测试!)
- 首先,我为每条记录分配了一个行号,这样我就可以根据您的限制为那些只有 1 行深的 ID 添加行...(CTE)请注意,我们按日期降序排列每个 ID,因此首先列出最新的记录。这样,如果同一天发生变化,第 2 行仍然是集合中的一条记录,并在联合中被淘汰;但如果一天只有 1 条记录,则先前的最新记录成为第 2 行,稍后通过 CT3 包含在数据集中。
- CTE2 根据规则将数据限制为您希望看到的数据
- 记录中的 CTE3 联合只有 1 行,因此您获得优先地位。这是有效的,因为我不关心重复的原因,因为联合消除了它们。
- 最后,我们使用 CTE2 的数据集填充来自 cte3 的数据以生成组合状态
- 使用包装查询消除末尾多余的“>”,然后离开。
.
WITH CTE AS (SELECT *, Row_number() over (PARTITION BY ID ORDER BY statusDate desc) RN FROM YourTable),
CTE2 as (SELECT * FROM cte WHERE StatusDate >= dateadd(DD, -1, cast(getdate() as date))
and _Status in ('Tracking', 'Approved', 'Reviewing', 'Received', 'Testing', 'Closed')),
CTE3 as (SELECT * FROM CTE2 UNION SELECT * FROM CTE where RN = 2 and ID in (SELECT ID FROM CTE2))
SELECT ID, left(_Status, len(_Status)-2) as _Status
FROM (SELECT Distinct t1.ID,
STUFF((SELECT t2._Status + ' > '
FROM CTE3 t2
WHERE t1.ID = t2.ID
ORDER BY StatusDate
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,0,'') _Status
from CTE2 t1) Z
结果:
ID _Status
101 Processing > Tracking
102 Approved > Reviewing > Approved
107 Tracking > Received
给猫剥皮的方法有很多;这只是 1。(众所周知的猫;不想受到动物爱好者的仇恨!)