我有以下表格。SQL複雜篩選器+數據透視表
用戶userID fullName
5 Mr. Joe
7 Mr. Bean
用品
id supplyDesc isActive
1 Ballpen 1
2 Adhesive Tape 1
3 White Paper 1
SupplyRequests
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
SupplyRequestDetails
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
您可能會注意到,我首先嚐試從Supplies表中獲取項目列表,並嘗試(但失敗)將每個項目標記給在給定條件下分別請求每個項目的用戶(日期範圍和活動狀態)。然後,創建了動態欄目並準備了物資的一個樞紐。另外,我還沒有弄清楚如何從這些查詢中統計所有唯一的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
整潔,但我不認爲supplyNames的靜態聲明會工作。耗材可能會不時變化。 – am0r
另外,由於動態項目,我不得不即興創建動態數據透視表。 – am0r
我改爲查詢動態供應商 –