简体   繁体   English

SQL 如何透视这个表?

[英]SQL How to Pivot this table?

I have a very hard time understanding how to pivot something.我很难理解如何旋转某些东西。

I have this simple query我有这个简单的查询

select 
year
,AVG(Quantity) Quantity
,AVG(Price) Price
,CAST(Datepart(wk,Date) as nvarchar) + '-' + RIGHT(CAST(year(Date) as NVARCHAR),2) Week
from Yearly
GROUP BY Year, CAST(Datepart(wk,Date) as nvarchar) + '-' + RIGHT(CAST(year(Date) as NVARCHAR),2)

Which results in this table这张表中的结果

+------+----------+---------------+------+
| year | Quantity |     Price     | Week |
+------+----------+---------------+------+
| 16   |   877814 | 68636081.39   | 6-20 |
| 17   |   436029 | 2635873.72    | 6-20 |
| 18   |  3793464 | 65971353.61   | 6-20 |
| 19   | 23552519 | 478741292.122 | 6-20 |
| 20   |  6973687 | 34658140.815  | 6-20 |
| Z01  |  7776508 | 54949609.221  | 6-20 |
+------+----------+---------------+------+

Right now I only have the one week, but as the days go by, I have a job that is going to build those 6 rows for 7-20, 8-20, 9-20, etc.现在我只有一周的时间,但随着时间的推移,我的工作是为 7-20、8-20、9-20 等构建 6 行。

I want my table to look like我希望我的桌子看起来像

+------+--------+-------------+--------+------------+---------+-------------+----------+-------------+---------+-------------+---------+-------------+----------+-------------+
|      |   16                 |   17                |   18                  |    19                  |   20                  |   Z01                 |  Total   |             |
+------+--------+-------------+--------+------------+---------+-------------+----------+-------------+---------+-------------+---------+-------------+----------+-------------+
| Week | Qty    | Price       | Qty    | Price      | Qty     | Price       | Qty      | Price       | Qty     | Price       | Qty     | Price       | Qty      | Price       |
| 6-20 | 877814 | 68636081.39 | 436029 | 2635873.72 | 3793464 | 65971353.61 | 23552519 | 478741292.1 | 6973687 | 34658140.82 | 7776508 | 54949609.22 | 43410021 | 705592350.9 |
| 7-20 |        |             |        |            |         |             |          |             |         |             |         |             |          |             |
| 8-20 |        |             |        |            |         |             |          |             |         |             |         |             |          |             |
+------+--------+-------------+--------+------------+---------+-------------+----------+-------------+---------+-------------+---------+-------------+----------+-------------+

Should I use Pivot or is there a better way to do this?我应该使用 Pivot 还是有更好的方法来做到这一点? If如果

This is a variation on pwilcox's answer, but more concise:这是 pwilcox 答案的变体,但更简洁:

select v.week,
       avg(case when year = 16 then quantity end) as quantityYr16,
       avg(case when year = 16 then price end) as priceYr16,
       avg(case when year = 17 then quantity end) as quantityYr17,
       avg(case when year = 17 then price end) as priceYr17,
       . . .
       sum(quantity) as totalQuantity,
       sum(price) as totalPrice
from yearly cross apply
     (values (concat(datename(week, date), '-', datename(year, date)))
     ) v(week)
group by v.week
order by v.week;

Notes:笔记:

  • Never use varchar() without a length.切勿使用没有长度的varchar() The default length varies by context and may not be long enough.默认长度因上下文而异,可能不够长。
  • datename() is a convenient function that returns strings and not numbers. datename()是一个方便的函数,它返回字符串而不是数字。
  • When using the date part functions, spell out the full names of the date parts -- week , year .使用日期部分函数时,请拼出日期部分的全名—— weekyear This makes the code easier to read.这使代码更易于阅读。

For a multi column pivot of the sort that you're wanting, you're going to have to take advantage of the fact that aggregate operations don't consider null values.对于您想要的那种多列数据透视,您将不得不利用聚合操作不考虑空值的事实。 So place case statements inside your averages that give the quantity or price value if associated with any given year, and null otherwise.因此,将 case 语句放在您的平均值中,如果与任何给定年份相关联,则给出数量或价格值,否则为 null。

select      ap.week,
            quantityYr16 = avg(case when year = 16 then quantity end),
            priceYr16 = avg(case when year = 16 then price end),
            quantityYr17 = avg(case when year = 17 then quantity end),
            priceYr17 = avg(case when year = 17 then price end),
            ...
from        yearly
cross apply (select week = 
                cast(datepart(wk,date) as nvarchar) + '-' + 
                right(cast(year(date) as nvarchar),2)
            ) ap
group by    ap.week

However, this structure is for reporting.但是,此结构用于报告。 SQL doesn't handle it as well as reporting tools such as HTML, SSRS or Excel. SQL 不会像 HTML、SSRS 或 Excel 等报告工具那样处理它。 I would do this operation with whatever reporting tool you ultimately report this with.我会使用您最终报告的任何报告工具来执行此操作。

Here is a PIVOT.这是一个枢轴。 Assumed you did not need Dynamic假设您不需要 Dynamic

Example例子

Select *
 From  ( 
        Select A.Week
              ,B.* 
         From  (
                  -- YOUR ORIGINAL QUERY HERE (without the Order By) --- 
               ) A
         Cross Apply ( values (concat(year,'_Qty')  ,[Quantity])
                             ,(concat(year,'_Price'),[Price])
                             ,(concat('Total','_Qty'),[Quantity])
                             ,(concat('Total','_Price'),[Price])
                     ) B(item,value) 
       ) src
 Pivot (sum(Value) for Item in ([16_Qty],[16_Price],[17_Qty],[17_Price],[18_Qty],[18_Price],[19_Qty],[19_Price],[20_Qty],[20_Price],[Z01_Qty],[Z01_Price],[Total_Qty],[Total_Price]) ) pvt 

Returns退货

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM