[英]SQL query for returning row values as columns - SQL Server 2008
I'm having trouble figuring out how to return a query result where I have row values that I want to turn into columns. 我无法弄清楚如何返回查询结果,其中我有行值,我想变成列。
In short, here is an example of my current schema in SQL Server 2008: 简而言之,这是我在SQL Server 2008中的当前架构的示例:
And here is an example of what I would like the query result to look like: 以下是我希望查询结果如下所示的示例:
Here is the SQLFiddle.com to play with - http://sqlfiddle.com/#!6/6b394/1/0 这是可以使用的SQLFiddle.com - http://sqlfiddle.com/#!6/6b394/1/0
Some helpful notes about the schema: 有关架构的一些有用说明:
As you can see, from the example desired end result image, the two rows are combined, and you can see each value has its own column with a relevant name. 如您所见,从示例所需的最终结果图像中,将两行组合在一起,您可以看到每个值都有自己的具有相关名称的列。
I've seen several examples of how this is possible, but not quite applicable for my purposes. 我已经看到了几个可能的例子,但不太适用于我的目的。 I've seen examples using Grouping and Case methods. 我见过使用分组和案例方法的例子。 I've seen many uses of PIVOT, and even some custom function creation in SQL. 我已经看到了PIVOT的许多用途,甚至在SQL中创建了一些自定义函数。 I'm not sure which is the best approach for me. 我不确定哪种方法最适合我。 Can I get some insight on this? 我可以对此有所了解吗?
There are many different ways that you can get the result. 您可以通过许多不同的方式获得结果。 Multiple JOINs, unpivot/pivot or CASE with aggregate. 多个JOIN,unpivot / pivot或带聚合的CASE。
They all have pros and cons, so you'll need to decide what will work best for your situation. 它们都有利有弊,所以你需要决定哪种方法最适合你的情况。
Multiple Joins - now you've stated that you will always have 2 rows for each day - one for apple and orange. 多个连接 - 现在您已经声明每天总共有2行 - 一个用于苹果和橙色。 When joining on the table multiple times your need some sort of column to join on. 多次加入桌面时,您需要某种列加入。 It appears the column is timestamp
but what happens if you have a day that you only get one row. 该列似乎是timestamp
但如果您有一天只能获得一行,会发生什么。 Then the INNER JOIN solution provided by @Becuzz won't work because it will only return the rows with both entries per day. 然后@Becuzz提供的INNER JOIN解决方案将无法工作,因为它只会返回每天包含两个条目的行。 LeYou could use multiple JOINs using a FULL JOIN
which will return the data even if there is only one entry per day: LeYou可以使用FULL JOIN
使用多个JOIN,即使每天只有一个条目,它也会返回数据:
select
[Timestamp] = Coalesce(a.Timestamp, o.Timestamp),
ApplesNumOffered = a.[NumOffered],
ApplesNumTaken = a.[NumTaken],
ApplesNumAbandoned = a.[NumAbandoned],
ApplesNumSpoiled = a.[NumSpoiled],
OrangesNumOffered = o.[NumOffered],
OrangesNumTaken = o.[NumTaken],
OrangesNumAbandoned = o.[NumAbandoned],
OrangesNumSpoiled = o.[NumSpoiled]
from
(
select timestamp, numoffered, NumTaken, numabandoned, numspoiled
from myTable
where FruitType = 'Apple'
) a
full join
(
select timestamp, numoffered, NumTaken, numabandoned, numspoiled
from myTable
where FruitType = 'Orange'
) o
on a.Timestamp = o.Timestamp
order by [timestamp];
See SQL Fiddle with Demo . 请参阅SQL Fiddle with Demo 。 Another issue with multiple joins is what if you have more than 2 values, you'll need an additional join for each value. 多个连接的另一个问题是,如果您有两个以上的值,则每个值都需要一个额外的连接。
If you have a limited number of values then I'd suggest using an aggregate function and a CASE expression to get the result: 如果您的值有限,那么我建议使用聚合函数和CASE表达式来获得结果:
SELECT
[timestamp],
sum(case when FruitType = 'Apple' then NumOffered else 0 end) AppleNumOffered,
sum(case when FruitType = 'Apple' then NumTaken else 0 end) AppleNumTaken,
sum(case when FruitType = 'Apple' then NumAbandoned else 0 end) AppleNumAbandoned,
sum(case when FruitType = 'Apple' then NumSpoiled else 0 end) AppleNumSpoiled,
sum(case when FruitType = 'Orange' then NumOffered else 0 end) OrangeNumOffered,
sum(case when FruitType = 'Orange' then NumTaken else 0 end) OrangeNumTaken,
sum(case when FruitType = 'Orange' then NumAbandoned else 0 end) OrangeNumAbandoned,
sum(case when FruitType = 'Orange' then NumSpoiled else 0 end) OrangeNumSpoiled
FROM myTable
group by [timestamp];
See SQL Fiddle with Demo . 请参阅SQL Fiddle with Demo 。 Or even using PIVOT/UNPIVOT like @M.Ali has. 甚至使用像@ M.Ali这样的PIVOT / UNPIVOT 。 The problem with these are what if you have unknown values - meaning more than just Apple
and Orange
. 如果你有未知的价值 - 这意味着不仅仅是Apple
和Orange
。 You are left with using dynamic SQL to get the result. 您将使用动态SQL来获取结果。 Dynamic SQL will create a string of sql that needs to be execute by the engine: 动态SQL将创建一个需要由引擎执行的sql字符串:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(FruitType + col)
from
(
select FruitType
from myTable
) d
cross apply
(
select 'NumOffered', 0 union all
select 'NumTaken', 1 union all
select 'NumAbandoned', 2 union all
select 'NumSpoiled', 3
) c (col, so)
group by FruitType, Col, so
order by FruitType, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT TimeStamp,' + @cols + '
from
(
select TimeStamp,
new_col = FruitType+col, value
from myTable
cross apply
(
select ''NumOffered'', NumOffered union all
select ''NumTaken'', NumOffered union all
select ''NumAbandoned'', NumOffered union all
select ''NumSpoiled'', NumOffered
) c (col, value)
) x
pivot
(
sum(value)
for new_col in (' + @cols + ')
) p '
exec sp_executesql @query;
See SQL Fiddle with Demo 请参阅SQL Fiddle with Demo
All versions give the result: 所有版本都给出了结果:
| timestamp | AppleNumOffered | AppleNumTaken | AppleNumAbandoned | AppleNumSpoiled | OrangeNumOffered | OrangeNumTaken | OrangeNumAbandoned | OrangeNumSpoiled |
|---------------------------|-----------------|---------------|-------------------|-----------------|------------------|----------------|--------------------|------------------|
| January, 01 2015 00:00:00 | 55 | 12 | 0 | 0 | 12 | 5 | 0 | 1 |
| January, 02 2015 00:00:00 | 21 | 6 | 2 | 1 | 60 | 43 | 0 | 0 |
| January, 03 2015 00:00:00 | 49 | 17 | 2 | 1 | 109 | 87 | 12 | 1 |
| January, 04 2015 00:00:00 | 6 | 4 | 0 | 0 | 53 | 40 | 0 | 1 |
| January, 05 2015 00:00:00 | 32 | 14 | 1 | 0 | 41 | 21 | 5 | 0 |
| January, 06 2015 00:00:00 | 26 | 24 | 0 | 1 | 97 | 30 | 10 | 1 |
| January, 07 2015 00:00:00 | 17 | 9 | 2 | 0 | 37 | 27 | 0 | 4 |
| January, 08 2015 00:00:00 | 83 | 80 | 3 | 0 | 117 | 100 | 5 | 1 |
Given your criteria, joining the two companion rows together and selecting out the appropriate fields seems like the simplest answer. 根据您的标准,将两个伴随行连接在一起并选择适当的字段似乎是最简单的答案。 You could go the route of PIVOTs, UNIONs and GROUP BYs, etc., but that seems like overkill. 你可以去PIVOTs,UNIONs和GROUP BYs等路线,但这看起来有点过分。
select apples.Timestamp
, apples.[NumOffered] as ApplesNumOffered
, apples.[NumTaken] as ApplesNumTaken
, apples.[NumAbandoned] as ApplesNumAbandoned
, apples.[NumSpoiled] as ApplesNumSpoiled
, oranges.[NumOffered] as OrangesNumOffered
, oranges.[NumTaken] as OrangesNumTaken
, oranges.[NumAbandoned] as OrangesNumAbandoned
, oranges.[NumSpoiled] as OrangesNumSpoiled
from myTable apples
inner join myTable oranges on oranges.Timestamp = apples.Timestamp
where apples.FruitType = 'Apple'
and oranges.FruitType = 'Orange'
Query 询问
;WITH CTE AS
(SELECT [Timestamp]
,FruitType + EventType AS Cols
,Qty
from myTable t
UNPIVOT (Qty FOR EventType IN (NumOffered ,NumTaken
,NumAbandoned,NumSpoiled))up
)
SELECT * FROM CTE
PIVOT (SUM(Qty) FOR Cols IN (AppleNumOffered,AppleNumTaken
,AppleNumAbandoned,AppleNumSpoiled
,OrangeNumOffered, OrangeNumTaken
,OrangeNumAbandoned,OrangeNumSpoiled))p
Result 结果
╔═════════════════════════╦═════════════════╦═══════════════╦═══════════════════╦═════════════════╦══════════════════╦════════════════╦════════════════════╦══════════════════╗
║ Timestamp ║ AppleNumOffered ║ AppleNumTaken ║ AppleNumAbandoned ║ AppleNumSpoiled ║ OrangeNumOffered ║ OrangeNumTaken ║ OrangeNumAbandoned ║ OrangeNumSpoiled ║
╠═════════════════════════╬═════════════════╬═══════════════╬═══════════════════╬═════════════════╬══════════════════╬════════════════╬════════════════════╬══════════════════╣
║ 2015-01-01 00:00:00.000 ║ 55 ║ 12 ║ 0 ║ 0 ║ 12 ║ 5 ║ 0 ║ 1 ║
║ 2015-01-02 00:00:00.000 ║ 21 ║ 6 ║ 2 ║ 1 ║ 60 ║ 43 ║ 0 ║ 0 ║
║ 2015-01-03 00:00:00.000 ║ 49 ║ 17 ║ 2 ║ 1 ║ 109 ║ 87 ║ 12 ║ 1 ║
║ 2015-01-04 00:00:00.000 ║ 6 ║ 4 ║ 0 ║ 0 ║ 53 ║ 40 ║ 0 ║ 1 ║
║ 2015-01-05 00:00:00.000 ║ 32 ║ 14 ║ 1 ║ 0 ║ 41 ║ 21 ║ 5 ║ 0 ║
║ 2015-01-06 00:00:00.000 ║ 26 ║ 24 ║ 0 ║ 1 ║ 97 ║ 30 ║ 10 ║ 1 ║
║ 2015-01-07 00:00:00.000 ║ 17 ║ 9 ║ 2 ║ 0 ║ 37 ║ 27 ║ 0 ║ 4 ║
║ 2015-01-08 00:00:00.000 ║ 83 ║ 80 ║ 3 ║ 0 ║ 117 ║ 100 ║ 5 ║ 1 ║
╚═════════════════════════╩═════════════════╩═══════════════╩═══════════════════╩═════════════════╩══════════════════╩════════════════╩════════════════════╩══════════════════╝
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.