0

I am really struggling with figuring out how to convert a MS Access CrossTab query into T-SQL to run on SQL2000 or into Linq-to-SQL. What I have is a query that looks like this in Access:

Access Cross Tab Query And produces this: Access Cross Tab Query Results

The query basically groups by ItemID and StoreID and Sums the Qty sold, but with the CrossTab query in Access, I am able to have a unique ItemID for each row, a column for each StoreID, and the total Qty for each StoreID/ItemID combination as the value.

How do you construct this in T-SQL 2000? I can build a simple select query with grouping, but it gives me the data in three columns, StoreID, ItemID, and Qty. But what I need is a column for ItemID and a column for every StoreID in the result set

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

Which produces this:

enter image description here

But what I really need to do is transform this data so that the StoreID values become columns, like the Access CrossTab query above.

GJGerson
  • 211
  • 1
  • 9
  • 20
  • I wouldn't typically do this in the SQL, I'd perform the cross tab in whatever reporting tool I was using. It's relatively simple using reporting services for example. – Bert Jul 21 '12 at 16:24
  • I agree. It just drives me nuts that something like this takes 2 seconds in Access but I can't figure it out in T-SQL or Linq-to-SQL. – GJGerson Jul 21 '12 at 16:53

1 Answers1

0

I would do this with dynamic SQL, since you probably don't know all of the store (TranSID) values in advance. This stored procedure takes start/end date as parameters, and generates a cross-tab. You can probably parameterize some of the other things as well, such as TranStatus and ItemClassID, but it wasn't clear if those are fixed or variable elements in your query.

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

So you can call it like this, to get everything from January 1st, 2005 until right now:

EXEC dbo.CrossTabByItem @StartDate = '20050101';

Or like this, to get just January of 2005:

EXEC dbo.CrossTabByItem @StartDate = '20050101', @EndDate = '20050131';
Aaron Bertrand
  • 272,866
  • 37
  • 466
  • 490
  • I created the stored procedure and ran it as is, but I get an error: "Incorrect syntax near the keyword 'GROUP'" – GJGerson Jul 21 '12 at 16:46
  • Sorry, all your unnecessary brackets led to a careless typo on my part. Please try now. – Aaron Bertrand Jul 21 '12 at 16:49
  • Bam! That got it. I am stunned and humbled. I will parameterize the ClassID and this will be good to go. Thanks a million!!! – GJGerson Jul 21 '12 at 17:00
  • Aaron, you helped me tremendously with this a while back and it has been working great in production, but I need to tweak it a little and I'm having hard time getting it to work. Any chance you could look at it again? – GJGerson Feb 13 '13 at 19:54
  • Here's a link to the new question I posted. [link](http://stackoverflow.com/questions/14862086/trouble-with-dynamic-t-sql-iif-statement) – GJGerson Feb 13 '13 at 20:14