SQL Server选择查询动态列输出

时间:2019-01-16 15:29:37

标签: sql sql-server sql-server-2008

我想在SQL Server 2008中完成以下任务

我有一个如下的文章表

| ArticleId | Description |
|-----------+-------------|
|         1 | Test        |
|-----------+-------------|

还有这样的订单预测表。

| 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列的顺序为预测表中的每个记录生成一个列。如果可能的话,我该怎么办?

| ArticleId | Description | Week51 | Week52 | Week1 | Week2 | Week3 |
|-----------+-------------+-----------------+-------+-------+-------+
|         1 | Test        |     0  |    150 |     0 |   200 |     0 |
|-----------+-------------+--------+--------+-------+-------+-------+

3 个答案:

答案 0 :(得分:1)

在一般情况下,SQL语言严格要求在查询编译时知道结果列的数量和数据类型。在准备好执行计划并开始查找数据后,您才能知道这里的要求。

因此,通常,您将能够做到的最好的操作是分三个步骤进行操作:

  1. 运行查询以告知您要使用的列。
  2. 使用#1的结果即时编写新查询。
  3. 执行新查询并返回结果

即使那样,通常也可以在客户端代码或报告工具中更好地处理这种枢纽。唯一的好消息是,仍然可以使用单个长SQL字符串在大多数平台上完成所有这些操作。

在这种特定情况下,您可以清楚地查看周数,因此可以通过假设所有53个可能的周前(而不是52个,因为年底有部分周)来解决此问题,并且编写一条大型SQL语句,该语句手动说明所有55列(53周+文章和说明)。

答案 1 :(得分:1)

提供的WEEK编号和Order编号是一致的,维护列顺序是一件小事。

您可能会注意到我使用#forecast和#article,因为我不知道您的实际表名。

示例

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

返回

ArticleID   Description Week51  Week52  Week1   Week2   Week3
1           Test        0       150     0       200     0

答案 2 :(得分:0)

您可以使用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

在这里,我使用查询作为表格,因为week的数字是1、2,但您希望将结果存储在Week1,Week2等中。因此,我将数字中的Week串联起来,并在Pivot查询中使用了它。 / p>

您可以找到实时演示Live Demo Here