【问题标题】:SQL Server select query dynamic column outputSQL Server 选择查询动态列输出
【发布时间】:2019-06-10 17:37:44
【问题描述】:

我想在 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 |
|-----------+-------------+--------+--------+-------+-------+-------+

【问题讨论】:

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


【解决方案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】:

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

    因此,您通常能做的最好的事情就是分三个单独的步骤运行:

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

    即便如此,这种数据透视通常在您的客户端代码或报告工具中得到更好的处理。唯一的好消息是,在大多数平台上,使用单个长 SQL 字符串仍然可以完成所有这些操作。

    对于这种特定情况,如果您清楚地查看周数,您可以通过预先假设所有可能的 53 周(不是 52,因为年底有部分周!)来解决这个问题,并且编写一个大型 SQL 语句,手动计算所有 55 列(53 周 + 文章和描述)。

    【讨论】:

    • 是的,我担心这就是答案,我需要的工具对脚本并不友好。这就是我的问题。
    【解决方案3】:

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

    这里我使用查询作为表,因为周是数字,如 1、2,但您希望结果在 Week1、Week2 等。所以我在数字中连接了单词 Week 并在 Pivot 查询中使用它。

    你可以找到现场演示Live Demo Here

    【讨论】:

      猜你喜欢
      • 2012-01-17
      • 2014-05-14
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      • 2017-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多