计算行中的特定值
Count specific values in rows
我有以下 table,我正在尝试计算每个客户在每个评估下的 POC 数量。
clientId ProcDate ProcDesc
7180 2018-06-13 Assessment
7180 2018-06-13 POC 20
7180 2018-06-13 POC 4b
7180 2018-06-20 POC 20
7180 2018-06-20 POC 4b
7180 2018-06-27 POC 20
7180 2018-06-27 POC 4b
7180 2018-07-04 Assessment
7180 2018-07-04 POC 20
7180 2018-07-04 POC 4b
7180 2018-07-11 POC 20
7180 2018-07-18 POC 20
7180 2018-07-18 POC 4b
7180 2018-09-05 Assessment
7180 2018-09-05 POC 20
7180 2018-09-12 POC 20
7180 2018-09-12 POC 4b
7180 2018-09-19 POC 20
7180 2018-09-19 POC 4b
2584 2018-10-03 Assessment
2584 2018-10-03 POC 20
2584 2018-10-03 POC 4b
2584 2018-11-04 Assessment
2584 2018-11-04 POC 20
2584 2018-11-04 POC 4b
2584 2018-11-11 POC 20
2584 2018-11-18 POC 20
2584 2018-11-18 POC 4b
7585 2018-11-04 Assessment
7585 2018-11-04 POC 20
7585 2018-11-04 POC 4b
7585 2018-11-11 POC 20
7585 2018-11-18 POC 20
7585 2018-11-18 POC 4b
6581 2018-11-04 CommAssessment
6581 2018-11-04 POC 20
6581 2018-11-04 POC 4b
6581 2018-11-11 POC 20
我想得到如下结果。
ClientId AssessDate Type CountPOC
7180 2018-06-13 Assessment 6
7180 2018-07-04 Assessment 5
7180 2018-09-05 Assessment 5
2584 2018-10-03 Assessment 2
2584 2018-11-04 Assessment 5
7585 2018-11-04 Assessment 5
6581 2018-11-04 CommAssessment 3
我不知道如何计算每次评估下的 POC 数量。
SELECT ClientId, ProcDate, ProcDesc
FROM ProcJoins
WHERE ProcDesc] in ('Assessment','POC 20','POC 4b')
GROUP BY ClientId, ProcDate, ProcDesc
ORDER BY ProcedureDate
这里有 2 个选项可以满足您的需求。
第一个假设每个客户总是从评估开始。
WITH CTE AS(
SELECT *,
ROW_NUMBER() OVER( ORDER BY clientId, ProcDate) rn
FROM ProcJoins
)
SELECT clientId,
ProcDate,
ProcDesc,
LEAD(rn, 1, t.totalProc) OVER(ORDER BY clientId, rn) - rn - 1
FROM CTE
CROSS JOIN( SELECT COUNT(*) + 1 AS totalProc FROM CTE) t
WHERE ProcDesc = 'Assessment'
ORDER BY clientId DESC, ProcDate;
第二个只是使用范围查询。
WITH CTE AS(
SELECT *,
LEAD(ProcDate, 1, '99990101') OVER(PARTITION BY clientId ORDER BY ProcDate) EndDate
FROM ProcJoins
WHERE ProcDesc = 'Assessment'
)
SELECT c.clientId,
c.ProcDate,
c.ProcDesc,
COUNT(*)
FROM CTE c
JOIN ProcJoins p ON p.ProcDate >= c.ProcDate
AND p.ProcDate < c.EndDate
AND p.clientId = c.clientId
WHERE p.ProcDesc <> 'Assessment'
GROUP BY c.clientId,
c.ProcDate,
c.ProcDesc
ORDER BY clientId DESC, ProcDate;
第三个选项与版本 2005、2008 和 2008R2 兼容
WITH CTE AS(
SELECT *,
ROW_NUMBER() OVER( PARTITION BY clientId ORDER BY ProcDate) rn
FROM ProcJoins
WHERE ProcDesc NOT LIKE 'POC%'
)
SELECT c.clientId,
c.ProcDate,
c.ProcDesc,
COUNT(*)
FROM CTE c
LEFT JOIN CTE n ON c.ClientId = n.clientId
AND c.rn = n.rn-1
JOIN ProcJoins p ON c.ClientId = p.clientId
AND c.ProcDate <= p.ProcDate
AND ISNULL(n.ProcDate, '99991231') > p.ProcDate
WHERE p.ProcDesc LIKE 'POC%'
GROUP BY c.clientId,
c.ProcDate,
c.ProcDesc
ORDER BY c.ProcDate;
示例数据:
declare @Test table
(ClientId int, ProcDate date,ProcDesc varchar(20))
insert @Test values
(7180,'2018-06-13','Assessment'),
(7180,'2018-06-13','POC 20'),
(7180,'2018-06-13','POC 4b'),
(7180,'2018-06-20','POC 20'),
(7180,'2018-06-20','POC 4b'),
(7180,'2018-06-27','POC 20'),
(7180,'2018-06-27','POC 4b'),
(7180,'2018-07-04','Assessment'),
(7180,'2018-07-04','POC 20'),
(7180,'2018-07-04','POC 4b'),
(7180,'2018-07-11','POC 20'),
(7180,'2018-07-18','POC 20'),
(7180,'2018-07-18','POC 4b'),
(7180,'2018-09-05','Assessment'),
(7180,'2018-09-05','POC 20'),
(7180,'2018-09-12','POC 20'),
(7180,'2018-09-12','POC 4b'),
(7180,'2018-09-19','POC 20'),
(7180,'2018-09-19','POC 4b'),
(2584,'2018-10-03','Assessment'),
(2584,'2018-10-03','POC 20'),
(2584,'2018-10-03','POC 4b'),
(2584,'2018-11-04','Assessment'),
(2584,'2018-11-04','POC 20'),
(2584,'2018-11-04','POC 4b'),
(2584,'2018-11-11','POC 20'),
(2584,'2018-11-18','POC 20'),
(2584,'2018-11-18','POC 4b'),
(7585,'2018-11-04','Assessment'),
(7585,'2018-11-04','POC 20'),
(7585,'2018-11-04','POC 4b'),
(7585,'2018-11-11','POC 20'),
(7585,'2018-11-18','POC 20'),
(7585,'2018-11-18','POC 4b'),
(1585,'2018-11-04','CommAssessment'),
(1585,'2018-11-04','POC 20'),
(1585,'2018-11-04','POC 4b'),
(1585,'2018-11-11','POC 20'),
(1585,'2018-11-18','POC 20'),
(1585,'2018-11-18','POC 4b')
建议的"old school"解决方案:
已编辑:我忘记了 "ClientId"
Fiddle
select ClientId, AssessDate = ProcDate, [Type] = ProcDesc, CountPOC = (
select count(*)
from @Test
where ProcDesc like 'POC%' --- <> 'Assessment'
and ClientId = t.ClientId
and ProcDate >= t.ProcDate
and ProcDate < isNull((
select top 1 ProcDate
from @Test
where ClientId = t.ClientId
and ProcDate > t.ProcDate
and ProcDesc not like 'POC%' -- = 'Assessment'
order by ProcDate
), getdate())
)
from @Test t
where t.ProcDesc not like 'POC%' -- = 'Assessment'
另一种可能的方法是定义组并获取计数:
输入:
CREATE TABLE #Data (
ClientId int,
ProcDate date,
ProcDesc varchar(10)
)
INSERT INTO #Data
(ClientId, ProcDate, ProcDesc)
VALUES
(7180, '20180613', 'Assessment'),
(7180, '20180613', 'POC 20'),
(7180, '20180613', 'POC 4b'),
(7180, '20180620', 'POC 20'),
(7180, '20180620', 'POC 4b'),
(7180, '20180627', 'POC 20'),
(7180, '20180627', 'POC 4b'),
(7180, '20180704', 'Assessment'),
(7180, '20180704', 'POC 20'),
(7180, '20180704', 'POC 4b'),
(7180, '20180711', 'POC 20'),
(7180, '20180718', 'POC 20'),
(7180, '20180718', 'POC 4b'),
(7180, '20180905', 'Assessment'),
(7180, '20180905', 'POC 20'),
(7180, '20180912', 'POC 20'),
(7180, '20180912', 'POC 4b'),
(7180, '20180919', 'POC 20'),
(7180, '20180919', 'POC 4b'),
(2584, '20181003', 'Assessment'),
(2584, '20181003', 'POC 20'),
(2584, '20181003', 'POC 4b'),
(2584, '20181104', 'Assessment'),
(2584, '20181104', 'POC 20'),
(2584, '20181104', 'POC 4b'),
(2584, '20181111', 'POC 20'),
(2584, '20181118', 'POC 20'),
(2584, '20181118', 'POC 4b'),
(7585, '20181104', 'Assessment'),
(7585, '20181104', 'POC 20'),
(7585, '20181104', 'POC 4b'),
(7585, '20181111', 'POC 20'),
(7585, '20181118', 'POC 20'),
(7585, '20181118', 'POC 4b'),
(6581, '20181104', 'CommAssessment'),
(6581, '20181104', 'POC 20'),
(6581, '20181104', 'POC 4b'),
(6581, '20181111', 'POC 20')
声明(如果支持SUM (...) OVER (ORDER BY ...)
):
;WITH GroupsCTE AS (
SELECT
ClientId, ProcDate, ProcDesc,
SUM(CASE WHEN ProcDesc IN ('Assessment', 'CommAssessment') THEN 1 ELSE 0 END)
OVER (ORDER BY ClientId, ProcDate, CASE WHEN ProcDesc IN ('Assessment', 'CommAssessment') THEN 0 ELSE 1 END) AS Groups
FROM #Data
), CountCTE AS (
SELECT
ClientId, ProcDate, ProcDesc,
COUNT(*) OVER (PARTITION BY Groups) AS [Count]
FROM GroupsCTE
)
SELECT
ClientId, ProcDate, ProcDesc, [Count] - 1
FROM CountCTE
WHERE ProcDesc IN ('Assessment', 'CommAssessment')
ORDER BY ClientId, ProcDate
声明(如果不支持SUM (...) OVER (ORDER BY ...)
):
;WITH GroupsCTE AS (
SELECT
d.ClientId, d.ProcDate, d.ProcDesc,
c.[Group]
FROM #Data d
CROSS APPLY(
SELECT
SUM(CASE WHEN ProcDesc IN ('Assessment', 'CommAssessment') THEN 1 ELSE 0 END) AS [Group]
FROM #Data
WHERE (ClientId = d.ClientId) AND (ProcDate <= d.ProcDate)
) c
), CountCTE AS (
SELECT ClientId, [Group], COUNT(*) - 1 AS [Count]
FROM GroupsCTE
GROUP BY ClientId, [Group]
)
SELECT
g.ClientId, g.ProcDate, g.ProcDesc,
c.[Count]
FROM GroupsCTE g
CROSS APPLY (
SELECT ClientId, [Group], COUNT(*) - 1 AS [Count]
FROM GroupsCTE
WHERE (ClientId = g.ClientId) AND ([Group] = g.[Group])
GROUP BY ClientId, [Group]
) c
WHERE g.ProcDesc IN ('Assessment', 'CommAssessment')
ORDER BY g.ClientId, g.ProcDate, CASE WHEN g.ProcDesc IN ('Assessment', 'CommAssessment') THEN 0 ELSE 1 END, g.ProcDesc
输出:
ClientId ProcDate ProcDesc (No column name)
2584 2018-10-03 Assessment 2
2584 2018-11-04 Assessment 5
6581 2018-11-04 CommAssessment 3
7180 2018-06-13 Assessment 6
7180 2018-07-04 Assessment 5
7180 2018-09-05 Assessment 5
7585 2018-11-04 Assessment 5
我有以下 table,我正在尝试计算每个客户在每个评估下的 POC 数量。
clientId ProcDate ProcDesc
7180 2018-06-13 Assessment
7180 2018-06-13 POC 20
7180 2018-06-13 POC 4b
7180 2018-06-20 POC 20
7180 2018-06-20 POC 4b
7180 2018-06-27 POC 20
7180 2018-06-27 POC 4b
7180 2018-07-04 Assessment
7180 2018-07-04 POC 20
7180 2018-07-04 POC 4b
7180 2018-07-11 POC 20
7180 2018-07-18 POC 20
7180 2018-07-18 POC 4b
7180 2018-09-05 Assessment
7180 2018-09-05 POC 20
7180 2018-09-12 POC 20
7180 2018-09-12 POC 4b
7180 2018-09-19 POC 20
7180 2018-09-19 POC 4b
2584 2018-10-03 Assessment
2584 2018-10-03 POC 20
2584 2018-10-03 POC 4b
2584 2018-11-04 Assessment
2584 2018-11-04 POC 20
2584 2018-11-04 POC 4b
2584 2018-11-11 POC 20
2584 2018-11-18 POC 20
2584 2018-11-18 POC 4b
7585 2018-11-04 Assessment
7585 2018-11-04 POC 20
7585 2018-11-04 POC 4b
7585 2018-11-11 POC 20
7585 2018-11-18 POC 20
7585 2018-11-18 POC 4b
6581 2018-11-04 CommAssessment
6581 2018-11-04 POC 20
6581 2018-11-04 POC 4b
6581 2018-11-11 POC 20
我想得到如下结果。
ClientId AssessDate Type CountPOC
7180 2018-06-13 Assessment 6
7180 2018-07-04 Assessment 5
7180 2018-09-05 Assessment 5
2584 2018-10-03 Assessment 2
2584 2018-11-04 Assessment 5
7585 2018-11-04 Assessment 5
6581 2018-11-04 CommAssessment 3
我不知道如何计算每次评估下的 POC 数量。
SELECT ClientId, ProcDate, ProcDesc
FROM ProcJoins
WHERE ProcDesc] in ('Assessment','POC 20','POC 4b')
GROUP BY ClientId, ProcDate, ProcDesc
ORDER BY ProcedureDate
这里有 2 个选项可以满足您的需求。
第一个假设每个客户总是从评估开始。
WITH CTE AS(
SELECT *,
ROW_NUMBER() OVER( ORDER BY clientId, ProcDate) rn
FROM ProcJoins
)
SELECT clientId,
ProcDate,
ProcDesc,
LEAD(rn, 1, t.totalProc) OVER(ORDER BY clientId, rn) - rn - 1
FROM CTE
CROSS JOIN( SELECT COUNT(*) + 1 AS totalProc FROM CTE) t
WHERE ProcDesc = 'Assessment'
ORDER BY clientId DESC, ProcDate;
第二个只是使用范围查询。
WITH CTE AS(
SELECT *,
LEAD(ProcDate, 1, '99990101') OVER(PARTITION BY clientId ORDER BY ProcDate) EndDate
FROM ProcJoins
WHERE ProcDesc = 'Assessment'
)
SELECT c.clientId,
c.ProcDate,
c.ProcDesc,
COUNT(*)
FROM CTE c
JOIN ProcJoins p ON p.ProcDate >= c.ProcDate
AND p.ProcDate < c.EndDate
AND p.clientId = c.clientId
WHERE p.ProcDesc <> 'Assessment'
GROUP BY c.clientId,
c.ProcDate,
c.ProcDesc
ORDER BY clientId DESC, ProcDate;
第三个选项与版本 2005、2008 和 2008R2 兼容
WITH CTE AS(
SELECT *,
ROW_NUMBER() OVER( PARTITION BY clientId ORDER BY ProcDate) rn
FROM ProcJoins
WHERE ProcDesc NOT LIKE 'POC%'
)
SELECT c.clientId,
c.ProcDate,
c.ProcDesc,
COUNT(*)
FROM CTE c
LEFT JOIN CTE n ON c.ClientId = n.clientId
AND c.rn = n.rn-1
JOIN ProcJoins p ON c.ClientId = p.clientId
AND c.ProcDate <= p.ProcDate
AND ISNULL(n.ProcDate, '99991231') > p.ProcDate
WHERE p.ProcDesc LIKE 'POC%'
GROUP BY c.clientId,
c.ProcDate,
c.ProcDesc
ORDER BY c.ProcDate;
示例数据:
declare @Test table
(ClientId int, ProcDate date,ProcDesc varchar(20))
insert @Test values
(7180,'2018-06-13','Assessment'),
(7180,'2018-06-13','POC 20'),
(7180,'2018-06-13','POC 4b'),
(7180,'2018-06-20','POC 20'),
(7180,'2018-06-20','POC 4b'),
(7180,'2018-06-27','POC 20'),
(7180,'2018-06-27','POC 4b'),
(7180,'2018-07-04','Assessment'),
(7180,'2018-07-04','POC 20'),
(7180,'2018-07-04','POC 4b'),
(7180,'2018-07-11','POC 20'),
(7180,'2018-07-18','POC 20'),
(7180,'2018-07-18','POC 4b'),
(7180,'2018-09-05','Assessment'),
(7180,'2018-09-05','POC 20'),
(7180,'2018-09-12','POC 20'),
(7180,'2018-09-12','POC 4b'),
(7180,'2018-09-19','POC 20'),
(7180,'2018-09-19','POC 4b'),
(2584,'2018-10-03','Assessment'),
(2584,'2018-10-03','POC 20'),
(2584,'2018-10-03','POC 4b'),
(2584,'2018-11-04','Assessment'),
(2584,'2018-11-04','POC 20'),
(2584,'2018-11-04','POC 4b'),
(2584,'2018-11-11','POC 20'),
(2584,'2018-11-18','POC 20'),
(2584,'2018-11-18','POC 4b'),
(7585,'2018-11-04','Assessment'),
(7585,'2018-11-04','POC 20'),
(7585,'2018-11-04','POC 4b'),
(7585,'2018-11-11','POC 20'),
(7585,'2018-11-18','POC 20'),
(7585,'2018-11-18','POC 4b'),
(1585,'2018-11-04','CommAssessment'),
(1585,'2018-11-04','POC 20'),
(1585,'2018-11-04','POC 4b'),
(1585,'2018-11-11','POC 20'),
(1585,'2018-11-18','POC 20'),
(1585,'2018-11-18','POC 4b')
建议的"old school"解决方案:
已编辑:我忘记了 "ClientId"
Fiddle
select ClientId, AssessDate = ProcDate, [Type] = ProcDesc, CountPOC = (
select count(*)
from @Test
where ProcDesc like 'POC%' --- <> 'Assessment'
and ClientId = t.ClientId
and ProcDate >= t.ProcDate
and ProcDate < isNull((
select top 1 ProcDate
from @Test
where ClientId = t.ClientId
and ProcDate > t.ProcDate
and ProcDesc not like 'POC%' -- = 'Assessment'
order by ProcDate
), getdate())
)
from @Test t
where t.ProcDesc not like 'POC%' -- = 'Assessment'
另一种可能的方法是定义组并获取计数:
输入:
CREATE TABLE #Data (
ClientId int,
ProcDate date,
ProcDesc varchar(10)
)
INSERT INTO #Data
(ClientId, ProcDate, ProcDesc)
VALUES
(7180, '20180613', 'Assessment'),
(7180, '20180613', 'POC 20'),
(7180, '20180613', 'POC 4b'),
(7180, '20180620', 'POC 20'),
(7180, '20180620', 'POC 4b'),
(7180, '20180627', 'POC 20'),
(7180, '20180627', 'POC 4b'),
(7180, '20180704', 'Assessment'),
(7180, '20180704', 'POC 20'),
(7180, '20180704', 'POC 4b'),
(7180, '20180711', 'POC 20'),
(7180, '20180718', 'POC 20'),
(7180, '20180718', 'POC 4b'),
(7180, '20180905', 'Assessment'),
(7180, '20180905', 'POC 20'),
(7180, '20180912', 'POC 20'),
(7180, '20180912', 'POC 4b'),
(7180, '20180919', 'POC 20'),
(7180, '20180919', 'POC 4b'),
(2584, '20181003', 'Assessment'),
(2584, '20181003', 'POC 20'),
(2584, '20181003', 'POC 4b'),
(2584, '20181104', 'Assessment'),
(2584, '20181104', 'POC 20'),
(2584, '20181104', 'POC 4b'),
(2584, '20181111', 'POC 20'),
(2584, '20181118', 'POC 20'),
(2584, '20181118', 'POC 4b'),
(7585, '20181104', 'Assessment'),
(7585, '20181104', 'POC 20'),
(7585, '20181104', 'POC 4b'),
(7585, '20181111', 'POC 20'),
(7585, '20181118', 'POC 20'),
(7585, '20181118', 'POC 4b'),
(6581, '20181104', 'CommAssessment'),
(6581, '20181104', 'POC 20'),
(6581, '20181104', 'POC 4b'),
(6581, '20181111', 'POC 20')
声明(如果支持SUM (...) OVER (ORDER BY ...)
):
;WITH GroupsCTE AS (
SELECT
ClientId, ProcDate, ProcDesc,
SUM(CASE WHEN ProcDesc IN ('Assessment', 'CommAssessment') THEN 1 ELSE 0 END)
OVER (ORDER BY ClientId, ProcDate, CASE WHEN ProcDesc IN ('Assessment', 'CommAssessment') THEN 0 ELSE 1 END) AS Groups
FROM #Data
), CountCTE AS (
SELECT
ClientId, ProcDate, ProcDesc,
COUNT(*) OVER (PARTITION BY Groups) AS [Count]
FROM GroupsCTE
)
SELECT
ClientId, ProcDate, ProcDesc, [Count] - 1
FROM CountCTE
WHERE ProcDesc IN ('Assessment', 'CommAssessment')
ORDER BY ClientId, ProcDate
声明(如果不支持SUM (...) OVER (ORDER BY ...)
):
;WITH GroupsCTE AS (
SELECT
d.ClientId, d.ProcDate, d.ProcDesc,
c.[Group]
FROM #Data d
CROSS APPLY(
SELECT
SUM(CASE WHEN ProcDesc IN ('Assessment', 'CommAssessment') THEN 1 ELSE 0 END) AS [Group]
FROM #Data
WHERE (ClientId = d.ClientId) AND (ProcDate <= d.ProcDate)
) c
), CountCTE AS (
SELECT ClientId, [Group], COUNT(*) - 1 AS [Count]
FROM GroupsCTE
GROUP BY ClientId, [Group]
)
SELECT
g.ClientId, g.ProcDate, g.ProcDesc,
c.[Count]
FROM GroupsCTE g
CROSS APPLY (
SELECT ClientId, [Group], COUNT(*) - 1 AS [Count]
FROM GroupsCTE
WHERE (ClientId = g.ClientId) AND ([Group] = g.[Group])
GROUP BY ClientId, [Group]
) c
WHERE g.ProcDesc IN ('Assessment', 'CommAssessment')
ORDER BY g.ClientId, g.ProcDate, CASE WHEN g.ProcDesc IN ('Assessment', 'CommAssessment') THEN 0 ELSE 1 END, g.ProcDesc
输出:
ClientId ProcDate ProcDesc (No column name)
2584 2018-10-03 Assessment 2
2584 2018-11-04 Assessment 5
6581 2018-11-04 CommAssessment 3
7180 2018-06-13 Assessment 6
7180 2018-07-04 Assessment 5
7180 2018-09-05 Assessment 5
7585 2018-11-04 Assessment 5