【问题标题】:SQL 2000 TSQL - Creating Pivot TableSQL 2000 TSQL - 创建数据透视表
【发布时间】:2012-07-20 13:48:04
【问题描述】:

我真的很想弄清楚如何将 MS Access CrossTab 查询转换为 T-SQL 以在 SQL2000 上运行或转换为 Linq-to-SQL。我有一个在 Access 中看起来像这样的查询:

并产生这个:

查询基本上按 ItemID 和 StoreID 分组,并对销售的数量求和,但使用 Access 中的 CrossTab 查询,我可以为每一行设置一个唯一的 ItemID,为每个 StoreID 设置一个列,以及每个 StoreID 的总数量/ItemID 组合作为值。

如何在 T-SQL 2000 中构造它?我可以使用分组构建一个简单的选择查询,但它提供了三列中的数据,StoreID、ItemID 和 Qty。但我需要的是 ItemID 的列和结果集中每个 StoreID 的列

SELECT     Trans.TranSID as StoreID, TransDetail.TranItemID as ItemID, SUM(TransDetail.Qty) AS TotalQtyForStore
    FROM         Trans INNER JOIN
                          TransDetail ON Trans.TranID = TransDetail.TranID INNER JOIN
                          Item ON TransDetail.TranItemID = Item.ItemID
    WHERE     (Trans.TranDate > CONVERT(DATETIME, '2005-01-01 00:00:00', 102)) AND (Trans.TranTypeID = 'so' OR
                          Trans.TranTypeID = 'ca') AND (Trans.TranStatus <> 'v') AND (Item.ItemClassID = 'RHM')
    GROUP BY Trans.TranSID, TransDetail.TranItemID

产生这个:

但我真正需要做的是转换这些数据,使 StoreID 值变成列,就像上面的 Access CrossTab 查询一样。

【问题讨论】:

  • 我通常不会在 SQL 中执行此操作,我会在我使用的任何报告工具中执行交叉表。例如,使用报告服务相对简单。
  • 我同意。它让我发疯,这样的事情在 Access 中需要 2 秒,但我无法在 T-SQL 或 Linq-to-SQL 中弄清楚。

标签: tsql linq-to-sql ms-access sql-server-2000 crosstab


【解决方案1】:

我会使用动态 SQL 来执行此操作,因为您可能事先不知道所有存储 (TranSID) 值。此存储过程将开始/结束日期作为参数,并生成一个交叉表。您可能还可以参数化其他一些东西,例如 TranStatus 和 ItemClassID,但不清楚它们是查询中的固定元素还是可变元素。

CREATE PROCEDURE dbo.CrossTabByItem
  @StartDate DATETIME,
  @EndDate   DATETIME = NULL
AS
BEGIN
  SET NOCOUNT ON;

  SET @EndDate = COALESCE(DATEADD(DAY, 1, @EndDate), GETDATE());

  DECLARE @sql NVARCHAR(4000); SET @sql = N'';

  SELECT @sql = @sql + ',
    [' + TranSID + '] = SUM(CASE WHEN t.TranSID = ''' 
    + TranSID + ''' THEN td.Qty ELSE 0 END)' FROM 
    (
      SELECT DISTINCT TranSID FROM dbo.Trans
      WHERE TranDate >= @StartDate AND TranDate < @EndDate
    ) AS x ORDER BY TranSID;

    SET @sql = N'SELECT ItemID = td.TranItemID' + @sql + '
      FROM dbo.Trans AS t
      INNER JOIN dbo.TransDetail AS td
       ON t.TranID = td.TranID
      INNER JOIN dbo.Item AS i
       ON td.TranItemID = i.ItemID
      WHERE t.TranDate >= @StartDate
      AND t.TranDate < @EndDate
      AND t.TranTypeID IN (''so'',''ca'')
      AND t.TranStatus <> ''v''
      AND i.ItemClassID = ''RHM''
      GROUP BY td.TranItemID;';

    EXEC sp_executesql @sql, 
      N'@StartDate DATETIME, @EndDate DATETIME', 
      @StartDate, @EndDate;
END
GO

所以你可以这样称呼它,以获取从 2005 年 1 月 1 日到现在的所有内容:

EXEC dbo.CrossTabByItem @StartDate = '20050101';

或者像这样,得到 2005 年 1 月:

EXEC dbo.CrossTabByItem @StartDate = '20050101', @EndDate = '20050131';

【讨论】:

  • 我创建了存储过程并按原样运行,但出现错误:“关键字'GROUP'附近的语法不正确”
  • 对不起,你所有不必要的括号导致我粗心的错字。请立即尝试。
  • 嘭!明白了。我感到震惊和谦卑。我将参数化 ClassID,这会很好。谢谢一百万!!!
  • Aaron,你在这方面帮了我很大的忙,它在生产中一直运行良好,但我需要稍微调整一下,我很难让它工作。有机会再看一遍吗?
  • 这是我发布的新问题的链接。 link
猜你喜欢
  • 2022-01-03
  • 1970-01-01
  • 2020-08-18
  • 2014-08-10
  • 2014-10-16
  • 2021-01-19
  • 2012-12-28
  • 1970-01-01
相关资源
最近更新 更多