我有以下表格。
userID fullName
5 Mr. Joe
7 Mr. Bean
id supplyDesc isActive
1 Ballpen 1
2 Adhesive Tape 1
3 White Paper 1
id requestCode forFrom forTo userID
1 SPR-2017-1 12-01-2017 02-28-2018 5
2 SPR-2017-2 12-01-2017 02-28-2018 7
3 SPR-2017-3 01-01-2018 03-31-2018 7
id rqID supplyID storeID qty isActive
1 1 1 1 1000 1
2 1 2 1 2000 1
3 1 1 12 2000 1
4 1 2 12 3000 1
5 1 1 13 3000 1
6 1 2 13 4000 1
7 2 1 10 100 1
8 2 2 10 200 1
9 2 1 11 200 1
10 2 2 11 300 1
11 3 1 10 1 1
12 3 2 10 2 1
13 3 1 11 2 1
14 3 2 11 3 1
要求:
在给定日期范围的情况下,获取所有用户的每个供应项目的相应总请求数量以及他们请求的唯一分支总数。必须是请求详细信息和供应表中的有效供应项目。
注意 耗材可能会不时变化
到目前为止我尝试了什么:
declare @forFrom varchar(50) = '12/01/2017'
declare @forTo varchar(50) = '02/28/2018'
declare @cols nvarchar(max), @cols2 nvarchar(max), @query NVARCHAR(MAX)
select @cols = STUFF((SELECT DISTINCT ', MAX(' + QUOTENAME(supplyDesc) + ')' + '''' + supplyDesc + ''''
FROM (select a.id'supplyID',
a.supplyDesc,
SUBSTRING(d.fullName, 5, LEN(MAX(d.fullName)))fullName,
SUM(CASE WHEN ((CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo)) THEN b.qty ELSE 0 END)totalQty
from Supplies a
left join SupplyRequestDetails b
on a.id = b.supplyID
left join SupplyRequests c
on b.rqID = c.id
left join Users d
on c.userID = d.id
where a.isActive = 1
or b.isActive = 1
group by a.id,
a.supplyDesc,
fullName
) as x
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
select @cols2 = STUFF((SELECT DISTINCT ',' + QUOTENAME(supplyDesc)
FROM (select a.id'supplyID',
a.supplyDesc,
SUBSTRING(d.fullName, 5, LEN(MAX(d.fullName)))fullName,
SUM(CASE WHEN ((CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo)) THEN b.qty ELSE 0 END)totalQty
from Supplies a
left join SupplyRequestDetails b
on a.id = b.supplyID
left join SupplyRequests c
on b.rqID = c.id
left join Users d
on c.userID = d.id
where a.isActive = 1
or b.isActive = 1
group by a.id,
a.supplyDesc,
fullName
) as x
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET @query = N'
declare @forFrom varchar(50) = ''12/01/2017''
declare @forTo varchar(50) = ''02/28/2018''
SELECT SUBSTRING(fullName, 5, LEN(fullName))fullName, ' + @cols + '
FROM (SELECT SUBSTRING(fullName, 5, LEN(fullName))fullName, ' + @cols + '
FROM (select a.id''supplyID'',
a.supplyDesc,
SUBSTRING(d.fullName, 5, LEN(MAX(d.fullName)))fullName,
SUM(CASE WHEN ((CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo)) THEN b.qty ELSE 0 END)totalQty
from Supplies a
left join SupplyRequestDetails b
on a.id = b.supplyID
left join SupplyRequests c
on b.rqID = c.id
left join Users d
on c.userID = d.id
where a.isActive = 1
or b.isActive = 1
group by a.id,
a.supplyDesc,
fullName
) as j
PIVOT (
SUM(totalQty) FOR supplyDesc IN ('
+ @cols2
+ ')
) AS a
WHERE fullName is not null
GROUP BY fullName
ORDER BY fullName;';
PRINT @query
EXEC sp_executesql @query
结果有点像:
fullName Ballpen Adhesive Tape White Paper
Mr.Joe 6303 9505 NULL
预期结果集:
fullName uqStores Ballpen Adhesive Tape White Paper
Mr. Joe 3 6000 4000 NULL
Mr. Bean 2 300 500 NULL
正如您可能注意到的那样,我首先尝试从“耗材”表中获取项目列表,然后尝试(但未通过)将每个项目标记给在给定条件(日期范围和活动状态)内分别请求每个项目的用户。然后,创建动态列并准备供应的枢轴。此外,我还没有弄清楚如何从这些查询中计算所有唯一的storeID。
我在想第一个问题是我是如何尝试将用户标记为每个项目的。但是,不知道如何同时使用一堆物品。
非常感谢您的帮助。
编辑:
我不得不修复一些问题。我相信我复制了错误的物品。
更新
fullName Ballpen Adhesive Tape White Paper
Mr. Joe 6000 9000 NULL
Mr. Bean 300 500 NULL
PS:不知何故,我一点一点地到达解决方案。现在我只需要按要求获得独特的商店。
更新
这似乎有效,但非常混乱。
DECLARE @forFrom varchar(50) = '12/01/2017'
DECLARE @forTo varchar(50) = '02/28/2018'
declare @cols nvarchar(max), @cols2 nvarchar(max), @query NVARCHAR(MAX)
select @cols = STUFF((SELECT DISTINCT ', MAX(' + QUOTENAME(supplyDesc) + ')' + '''' + supplyDesc + ''''
FROM (select DISTINCT a.id'supplyID',
a.supplyDesc,
COUNT(CASE WHEN ((CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo)) THEN b.storeID ELSE NULL END)numberOfStores,
SUBSTRING(d.fullName, 5, LEN(MAX(CASE WHEN (CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo) THEN d.fullName ELSE NULL END)))fullName,
SUM(CASE WHEN ((CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo)) THEN b.qty ELSE 0 END)totalQty
from Supplies a
left join SupplyRequestDetails b
on a.id = b.supplyID
left join SupplyRequests c
on b.rqID = c.id
left join Users d
on c.userID = d.id
where a.isActive = 1
or b.isActive = 1
group by a.id,
a.supplyDesc,
fullName
) as x
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
select @cols2 = STUFF((SELECT DISTINCT ',' + QUOTENAME(supplyDesc)
FROM (select DISTINCT a.id'supplyID',
a.supplyDesc,
COUNT(CASE WHEN ((CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo)) THEN b.storeID ELSE NULL END)numberOfStores,
SUBSTRING(d.fullName, 5, LEN(MAX(CASE WHEN (CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo) THEN d.fullName ELSE NULL END)))fullName,
SUM(CASE WHEN ((CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo)) THEN b.qty ELSE 0 END)totalQty
from Supplies a
left join SupplyRequestDetails b
on a.id = b.supplyID
left join SupplyRequests c
on b.rqID = c.id
left join Users d
on c.userID = d.id
where a.isActive = 1
or b.isActive = 1
group by a.id,
a.supplyDesc,
fullName
) as x
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET @query = N'
declare @forFrom varchar(50) = ''' + @forFrom + '''
declare @forTo varchar(50) = ''' + @forTo + '''
SELECT SUBSTRING(fullName, 5, LEN(fullName))fullName, COUNT(numberOfStores)numOfStores,' + @cols + '
FROM (select DISTINCT a.id''supplyID'',
a.supplyDesc,
COUNT(CASE WHEN ((CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo)) THEN b.storeID ELSE NULL END)numberOfStores,
SUBSTRING(d.fullName, 5, LEN(MAX(CASE WHEN (CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo) THEN d.fullName ELSE NULL END)))fullName,
SUM(CASE WHEN ((CAST(c.forFrom as datetime) >= @forFrom and CAST(c.forTo as datetime) <= @forTo)) THEN b.qty ELSE 0 END)totalQty
from Supplies a
left join SupplyRequestDetails b
on a.id = b.supplyID
left join SupplyRequests c
on b.rqID = c.id
left join Users d
on c.userID = d.id
where a.isActive = 1
or b.isActive = 1
group by a.id,
a.supplyDesc,
fullName
) as j
PIVOT (
SUM(totalQty) FOR supplyDesc IN ('
+ @cols2
+ ')
) AS a
WHERE fullName is not null
GROUP BY fullName
ORDER BY fullName;';
EXEC sp_executesql @query
当然有更好的方法来做到这一点。我真的很喜欢你的建议。
更新
从@sarslan的答案中得出并编辑:
DECLARE @Query NVARCHAR(MAX) = '
SELECT * FROM (
SELECT
S.supplyDesc
, fullName
, COUNT(DISTINCT storeID) [uqStores]
, SUM(qty) SumQty
FROM
Supplies S
LEFT JOIN ( SELECT U.fullName, supplyID, storeID, qty, SRD.isActive FROM SupplyRequestDetails SRD
INNER JOIN SupplyRequests SR ON SRD.rqID = SR.id AND ( SR.forFrom >= @forFrom AND SR.forTo <= @forTo )
INNER JOIN Users U ON SR.userID = U.userID ) AS ST ON ST.supplyID = S.id
WHERE ST.isActive = 1
GROUP BY fullName, supplyDesc
HAVING COUNT(DISTINCT storeID) > 1
) SRC
PIVOT ( SUM (SumQty) FOR supplyDesc IN ( ' + @ColNames + ')) PVT '
比方说,例如,SupplyRequestDetails中id为1的项目将变为非活动状态。
结果是:
fullName Ballpen Adhesive Tape White Paper
Mr. Bean 5000 NULL NULL
Mr. Bean NULL 9000 NULL
Mr. Joe 300 500 NULL
答案 0 :(得分:1)
您可以使用此脚本。
declare @forFrom datetime = '12/01/2017'
declare @forTo datetime = '02/28/2018'
DECLARE @ColNames NVARCHAR(MAX)= ''
SELECT @ColNames = @ColNames + ',' + QUOTENAME (supplyDesc) FROM Supplies WHERE isActive = 1
SET @ColNames = STUFF(@ColNames,1,1,'')
DECLARE @Query NVARCHAR(MAX) = '
SELECT * FROM (
SELECT
S.supplyDesc
, fullName
, COUNT(DISTINCT storeID) [uqStores]
, SUM(qty) SumQty
FROM
Supplies S
LEFT JOIN ( SELECT U.fullName, supplyID, storeID, qty, SRD.isActive FROM SupplyRequestDetails SRD
INNER JOIN SupplyRequests SR ON SRD.rqID = SR.id AND ( SR.forFrom >= @forFrom AND SR.forTo <= @forTo )
INNER JOIN Users U ON SR.userID = U.userID
WHERE SRD.isActive = 1 ) AS ST ON ST.supplyID = S.id
WHERE S.isActive = 1
GROUP BY fullName, supplyDesc
HAVING COUNT(DISTINCT storeID) > 1
) SRC
PIVOT ( SUM (SumQty) FOR supplyDesc IN ( ' + @ColNames + ')) PVT '
EXEC sp_executesql @Query, N'@forFrom DATETIME, @forTo DATETIME' , @forFrom = @forFrom, @forTo = @forTo
结果:
fullName uqStores Ballpen Adhesive Tape White Paper
-------------------- ----------- ----------- ------------- -----------
Mr. Bean 2 300 500 NULL
Mr. Joe 3 6000 9000 NULL