【发布时间】:2020-01-31 20:39:31
【问题描述】:
我有一个简单的发票表,其中包含每件售出的商品及其售出日期。
以下是获取基本数据库并计算每件商品每周售出次数的一些示例数据。
+------+-----------------+------------+---------+
| Week | Item_Number | Color_Code | Touches |
+------+-----------------+------------+---------+
| 1 | 11073900LRGMO | 02000 | 7 |
| 1 | 11073900MEDMO | 02000 | 9 |
| 2 | 1114900011BMO | 38301 | 62 |
| 2 | 1114910012BMO | 21701 | 147 |
| 2 | 1114910012BMO | 38301 | 147 |
| 2 | 1114910012BMO | 46260 | 147 |
| 3 | 13MK430R03R | 00101 | 2 |
| 3 | 13MK430R03R | 10001 | 2 |
| 3 | 13MK430R03R | 65004 | 8 |
| 3 | 13MK430R03S | 00101 | 2 |
| 3 | 13MK430R03S | 10001 | 2 |
+------+-----------------+------------+---------+
然后我使用动态查询和数据透视运算符从这些数据中创建了一个矩阵。这是我的做法,
首先,我创建一个临时表
DECLARE @cols AS NVARCHAR(MAX)
DECLARE @query AS NVARCHAR(MAX)
IF OBJECT_ID('tempdb..#VTable') IS NOT NULL
DROP TABLE #VTable
CREATE TABLE #VTable
(
[Item_Number] NVARCHAR(100),
[Color_Code] NVARCHAR(100),
[Item_Cost] NVARCHAR(100),
[Week] NVARCHAR(10),
[xCount] int
);
然后我将我的数据插入到那个表中,
INSERT INTO #VTable
(
[Item_Number],
[Color_Code],
[Item_Cost],
[Week],
[xCount]
)
SELECT
*
FROM (
SELECT
Item_Number
,Color_Code
,Item_Cost
,Week
,Count(Item_Number) Touches
FROM (
SELECT
DATEPART (year, I.Date_Invoiced) Year
,DATEPART (month, I.Date_Invoiced) Month
,Concat(CASE WHEN DATEPART (week, I.Date_Invoiced) <10 THEN CONCAT('0',DATEPART (week, I.Date_Invoiced)) ELSE CAST(DATEPART (week, I.Date_Invoiced) AS NVARCHAR) END,'-',RIGHT(DATEPART (year, I.Date_Invoiced),2) ) WEEK
,DATEPART (day, I.Date_Invoiced) Day
,I.Invoice_Number
,I.Customer_Number
,I.Warehouse_Code
,S.Pack_Type
,S.Quantity_Per_Carton
,S.Inner_Pack_Quantity
,LTRIM(RTRIM(ID.Item_Number)) Item_Number
,LTRIM(RTRIM(ID.Color_Code)) Color_Code
,CASE
WHEN ISNULL(s.Actual_Cost, 0) = 0
THEN ISNULL(s.Standard_Cost, 0)
ELSE s.Actual_Cost
END Item_Cost
,ID.Quantity
,case when s.Pack_Type='carton' then id.Quantity/s.Quantity_Per_Carton when s.Pack_Type='Inner Poly' then id.Quantity/s.Inner_Pack_Quantity end qty
,ID.Line_Number
FROM Invoices I
LEFT JOIN Invoices_Detail ID on I.Company_Code = ID.Company_Code and I.Division_Code = ID.Division_Code and I.Invoice_Number = ID.Invoice_Number
LEFT JOIN Style S on I.Company_Code = S.Company_Code and I.Division_Code = S.Division_Code and ID.Item_Number = S.Item_Number and ID.Color_Code = S.Color_Code
WHERE 1=1
AND (I.Company_Code = @LocalCompanyCode OR @LocalCompanyCode IS NULL)
AND (I.Division_Code = @LocalDivisionCode OR @LocalDivisionCode IS NULL)
AND (I.Warehouse_Code = @LocalWarehouse OR @LocalWarehouse IS NULL)
AND (S.Pack_Type = @LocalPackType OR @LocalPackType IS NULL)
AND (I.Customer_Number = @LocalCustomerNumber OR @LocalCustomerNumber IS NULL)
AND (I.Date_Invoiced Between @LocalFromDate And @LocalToDate)
) T
GROUP BY Item_Number,Color_Code,Item_Cost,Week
) TT
然后我使用动态查询来创建矩阵:
select @cols = STUFF((SELECT ',' + QUOTENAME(Week)
from #VTable
group by Week
order by (Right(Week,2) + LEFT(Week,2))
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = '
SELECT
*
FROM (
SELECT Item_Number,Color_Code, Item_Cost,' + @cols + ' from
(
select Item_Number, Color_Code, Item_Cost, week, xCount
from #Vtable
) x
pivot
(
sum(xCount)
for week in (' + @cols + ')
) p
)T
'
execute(@query);
这给了我我正在寻找的东西,这是矩阵的样子。
+---------------+------------+-----------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
| Item_Number | Color_Code | Item_Cost | 36-18 | 37-18 | 38-18 | 39-18 | 40-18 | 41-18 | 42-18 | 43-18 | 44-18 | 45-18 | 46-18 | 47-18 | 48-18 | 49-18 | 50-18 | 51-18 | 52-18 | 53-18 | 01-19 | 02-19 | 03-19 | 04-19 | 05-19 | 06-19 | 07-19 | 08-19 | 09-19 | 10-19 | 11-19 | 12-19 | 13-19 | 14-19 | 15-19 | 16-19 | 17-19 | 18-19 | 19-19 | 20-19 | 21-19 | 22-19 | 23-19 | 24-19 | 25-19 | 26-19 | 27-19 | 28-19 | 29-19 | 30-19 | 31-19 | 32-19 | 33-19 | 34-19 | 35-19 |
+---------------+------------+-----------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
| 11073900LRGMO | 02000 | 8.51 | 1 | NULL | 13 | NULL | 3 | NULL | NULL | 3 | 3 | NULL | 4 | 3 | 6 | NULL | 4 | NULL | NULL | NULL | 7 | 4 | NULL | 3 | 2 | 5 | 30 | 7 | 3 | 10 | NULL | 9 | 19 | 5 | NULL | 10 | 9 | 5 | 2 | 3 | 5 | 4 | 3 | 9 | 7 | NULL | 5 | 1 | 3 | 5 | NULL | NULL | 11 | 7 | 3 |
| 11073900MEDMO | 02000 | 8.49 | 11 | NULL | 22 | NULL | 5 | NULL | NULL | 14 | 4 | NULL | 4 | 3 | 8 | NULL | 9 | NULL | NULL | NULL | 9 | 3 | NULL | 7 | 6 | 4 | 37 | 10 | 8 | 9 | NULL | 7 | 30 | 14 | NULL | 12 | 5 | 7 | 8 | 7 | 2 | 4 | 6 | 15 | 4 | NULL | 2 | 7 | 3 | 7 | NULL | NULL | 11 | 9 | 3 |
| 11073900SMLMO | 02000 | 8.50 | 6 | NULL | 18 | NULL | 3 | NULL | NULL | 3 | 7 | NULL | 5 | NULL | 7 | NULL | 9 | NULL | NULL | NULL | 7 | 4 | NULL | 7 | 2 | 6 | 37 | 9 | 4 | 7 | NULL | 7 | 19 | 7 | NULL | 11 | 5 | 7 | 7 | 2 | 3 | 8 | 8 | 9 | 2 | NULL | 2 | 2 | 2 | 4 | NULL | NULL | 8 | 5 | 4 |
| 11073900XLGMO | 02000 | 8.51 | 2 | NULL | 6 | NULL | 3 | NULL | NULL | 2 | 4 | NULL | 3 | 1 | 3 | NULL | 4 | NULL | NULL | NULL | 4 | 4 | NULL | NULL | 3 | 1 | 27 | 4 | 3 | 4 | NULL | 8 | 11 | 9 | NULL | 7 | 2 | 4 | 1 | 5 | 1 | 6 | 5 | 6 | 1 | NULL | 1 | 3 | NULL | 3 | NULL | NULL | 3 | 4 | 2 |
+---------------+------------+-----------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
我要做的最后一件事是找到一种对这张表进行排序的好方法。我认为最好的方法是按照在所有星期中选择最多的项目编号进行排序。逐列求和将为我提供所有项目每周的触摸总数,但我想做一个逐行求和,其中最后有另一列包含每个项目的触摸。有谁知道我会怎么做?我尝试过使用此链接中的另一个动态查询 -> (calculate Row Wise Sum - Sql server) 但我无法让它工作。
【问题讨论】:
-
您只是在问如何将订单添加到您的动态 sql 中吗?
-
不,我想创建一个名为 totalCount 之类的新列,它将每个项目的每周计数求和(因此按行排列),然后按该列排序。
-
为什么不直接创建另一个变量,如@cols,用+而不是逗号分隔?然后你只需将它添加到你的动态 sql 中,它就会将所有列添加在一起。在这一点上,顺序应该是微不足道的。
标签: sql sql-server dynamic pivot