我真的很想弄清楚如何将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查询一样。
答案 0 :(得分:0)
我会使用动态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';