SQL服务器select查询动态列输出
SQL Server select query dynamic column output
我想在 SQL Server 2008
中完成以下任务
我有一篇文章table如下
| ArticleId | Description |
|-----------+-------------|
| 1 | Test |
|-----------+-------------|
还有这样的订单预测table。
| ArticleId | Week | Order | Amount |
|-----------+--------------+--------+
| 1 | 51 | 1 | 0 |
| 1 | 52 | 2 | 150 |
| 1 | 1 | 3 | 0 |
| 1 | 2 | 4 | 200 |
| 1 | 3 | 5 | 0 |
|-----------+------+-------+--------+
有没有一种方法可以创建一个查询,该查询会按照 order
列的顺序为预测 table 中的每条记录生成一个列。如果可能的话我该怎么做?
| ArticleId | Description | Week51 | Week52 | Week1 | Week2 | Week3 |
|-----------+-------------+-----------------+-------+-------+-------+
| 1 | Test | 0 | 150 | 0 | 200 | 0 |
|-----------+-------------+--------+--------+-------+-------+-------+
在一般情况下,SQL 语言严格要求在查询编译时知道结果列的数量和数据类型。只有在准备好执行计划并开始查看数据后,才能知道您在这里要求的内容。
因此,一般来说,您最多可以做到 运行 这分为三个独立的步骤:
- 运行 一个查询,告诉您要使用的列。
- 使用 #1 的结果即时编写新查询。
- 执行新查询并return结果
即便如此,这种数据透视通常在您的客户端代码或报告工具中得到更好的处理。唯一的好消息是,仍然可以在大多数平台上使用一个长 SQL 字符串来完成所有这些操作。
对于这种特定情况,您清楚地查看周数,您可以通过预先假设所有可能的 53 周(而不是 52 周,因为年底有部分周!)来解决这个问题。 ,并编写一个大型 SQL 语句,手动说明所有 55 列(53 周 + 文章和描述)。
您可以使用 Pivot 尝试以下查询以获得您想要的结果。
Create Table Article (ArticleId Int, [Description] Varchar(10))
Insert Into Article Values (1, 'Test')
Create Table OrderForecast(ArticleId Int, [Week] Int, [Order] Int, Amount Int)
Insert Into OrderForecast Values (1, 51, 1, 0),(1, 52, 2, 150), (1, 1, 3, 0),(1, 2, 4, 200), (1, 3, 5,0)
Select ArticleId, [Description], Week51, Week52, Week1, Week2, Week3
from
(
select ArticleId, [Description], Amount, [Week]
from
(
SELECT OrderForecast.ArticleId, 'Week' + Convert(Varchar(10), OrderForecast.[Week]) as [Week], [Order], Amount,
Article.[Description] as [Description] FROM OrderForecast
Inner Join Article On OrderForecast.ArticleId = Article.ArticleId
)a
) d
pivot
(
max(Amount)
for [Week] in (Week51, Week52, Week1, Week2, Week3)
) piv;
结果如下图
ArticleId Description Week51 Week52 Week1 Week2 Week3
-------------------------------------------------------------
1 Test 0 150 0 200 0
这里我使用查询作为 table 因为周的数字是 1、2,但你想要第 1、第 2 周等的结果。所以我在数字中连接了单词 Week 并使用了它在数据透视查询中。
您可以找到现场演示 Live Demo Here
只要WEEK号和Order号一致,保持列序是小事
您可能注意到我使用了#forecast 和#article,因为我不知道您的 table 真实姓名。
例子
Declare @SQL varchar(max) = '
Select *
From (
Select A.ArticleID
,D.Description
,B.*
From #forecast A
Join #article D on A.ArticleID=D.ArticleID
Cross Apply (values (''Week''+left(Week,4),Amount) ) B(Item,Value)
) A
Pivot (max([Value])
For [Item] in (' + Stuff((Select ','+QuoteName('Week'+left(Week,4))
From (Select Distinct top 100 [Order],Week From #forecast Order by [Order] ) A
For XML Path('')),1,1,'') + ') ) p'
Exec(@SQL);
--Print @SQL
Returns
ArticleID Description Week51 Week52 Week1 Week2 Week3
1 Test 0 150 0 200 0
我想在 SQL Server 2008
中完成以下任务我有一篇文章table如下
| ArticleId | Description |
|-----------+-------------|
| 1 | Test |
|-----------+-------------|
还有这样的订单预测table。
| ArticleId | Week | Order | Amount |
|-----------+--------------+--------+
| 1 | 51 | 1 | 0 |
| 1 | 52 | 2 | 150 |
| 1 | 1 | 3 | 0 |
| 1 | 2 | 4 | 200 |
| 1 | 3 | 5 | 0 |
|-----------+------+-------+--------+
有没有一种方法可以创建一个查询,该查询会按照 order
列的顺序为预测 table 中的每条记录生成一个列。如果可能的话我该怎么做?
| ArticleId | Description | Week51 | Week52 | Week1 | Week2 | Week3 |
|-----------+-------------+-----------------+-------+-------+-------+
| 1 | Test | 0 | 150 | 0 | 200 | 0 |
|-----------+-------------+--------+--------+-------+-------+-------+
在一般情况下,SQL 语言严格要求在查询编译时知道结果列的数量和数据类型。只有在准备好执行计划并开始查看数据后,才能知道您在这里要求的内容。
因此,一般来说,您最多可以做到 运行 这分为三个独立的步骤:
- 运行 一个查询,告诉您要使用的列。
- 使用 #1 的结果即时编写新查询。
- 执行新查询并return结果
即便如此,这种数据透视通常在您的客户端代码或报告工具中得到更好的处理。唯一的好消息是,仍然可以在大多数平台上使用一个长 SQL 字符串来完成所有这些操作。
对于这种特定情况,您清楚地查看周数,您可以通过预先假设所有可能的 53 周(而不是 52 周,因为年底有部分周!)来解决这个问题。 ,并编写一个大型 SQL 语句,手动说明所有 55 列(53 周 + 文章和描述)。
您可以使用 Pivot 尝试以下查询以获得您想要的结果。
Create Table Article (ArticleId Int, [Description] Varchar(10))
Insert Into Article Values (1, 'Test')
Create Table OrderForecast(ArticleId Int, [Week] Int, [Order] Int, Amount Int)
Insert Into OrderForecast Values (1, 51, 1, 0),(1, 52, 2, 150), (1, 1, 3, 0),(1, 2, 4, 200), (1, 3, 5,0)
Select ArticleId, [Description], Week51, Week52, Week1, Week2, Week3
from
(
select ArticleId, [Description], Amount, [Week]
from
(
SELECT OrderForecast.ArticleId, 'Week' + Convert(Varchar(10), OrderForecast.[Week]) as [Week], [Order], Amount,
Article.[Description] as [Description] FROM OrderForecast
Inner Join Article On OrderForecast.ArticleId = Article.ArticleId
)a
) d
pivot
(
max(Amount)
for [Week] in (Week51, Week52, Week1, Week2, Week3)
) piv;
结果如下图
ArticleId Description Week51 Week52 Week1 Week2 Week3
-------------------------------------------------------------
1 Test 0 150 0 200 0
这里我使用查询作为 table 因为周的数字是 1、2,但你想要第 1、第 2 周等的结果。所以我在数字中连接了单词 Week 并使用了它在数据透视查询中。
您可以找到现场演示 Live Demo Here
只要WEEK号和Order号一致,保持列序是小事
您可能注意到我使用了#forecast 和#article,因为我不知道您的 table 真实姓名。
例子
Declare @SQL varchar(max) = '
Select *
From (
Select A.ArticleID
,D.Description
,B.*
From #forecast A
Join #article D on A.ArticleID=D.ArticleID
Cross Apply (values (''Week''+left(Week,4),Amount) ) B(Item,Value)
) A
Pivot (max([Value])
For [Item] in (' + Stuff((Select ','+QuoteName('Week'+left(Week,4))
From (Select Distinct top 100 [Order],Week From #forecast Order by [Order] ) A
For XML Path('')),1,1,'') + ') ) p'
Exec(@SQL);
--Print @SQL
Returns
ArticleID Description Week51 Week52 Week1 Week2 Week3
1 Test 0 150 0 200 0