使用Pivot将多个表连接到动态表中

时间:2013-02-04 17:43:11

标签: sql sql-server-2008 join pivot

此代码现在显示来自多个表的信息,这些表是透视的 好的,所以这段代码现在几乎可以按照我的意愿运行(目前正在处理它,没有其他问题):

if (exists (select * from tempdb.INFORMATION_SCHEMA.TABLES where TABLE_NAME = '##tempz'))
begin
drop table ##tempz
end
else
DECLARE @startDate datetime
DECLARE @enddate datetime
DECLARE @registernum int
DECLARE @storename varchar(20)
DECLARE @cashiername varchar(20)
SET @startDate = '1/1/2011'
SET @enddate = '1/1/2013'
SET @registernum = 01
SET @storename = '01'
SET @cashiername = 'admin'

DECLARE @cols AS NVARCHAR(MAX),@colsNull AS NVARCHAR(MAX),@query  AS NVARCHAR(MAX)
SELECT @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(c.CurrencyDesc)
FROM rpPay p LEFT JOIN RPTrs r ON p.ReceiptNo = r.ReceiptNo LEFT JOIN Currencies c ON c.POSCurrency = LEFT(p.paytype,1)
WHERE r.trsdate >= @startDate AND r.trsdate <= @enddate
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'),1,1,'')

SELECT @colsNull = STUFF((SELECT DISTINCT ', IsNull(' + QUOTENAME(c.CurrencyDesc) +', 0) as '+ QUOTENAME(c.CurrencyDesc)
FROM rpPay p LEFT JOIN RPTrs r ON p.ReceiptNo = r.ReceiptNo LEFT JOIN Currencies c ON LEFT(p.paytype,1) = c.POSCurrency
WHERE r.trsdate >= @startDate AND r.trsdate <= @enddate
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'),1,1,'')

--select @cols, @colsnull

SET @query = 'select date, cashregister, storeid, cashier, '+@colsNull+' into ##tempz
FROM
(SELECT cast(r.trsdate AS DATE) date,c.CurrencyDesc,p.amount,r.cashregister,r.storeid,r.cashier
FROM rpPay p LEFT JOIN RPTrs r ON p.ReceiptNo = r.receiptno LEFT JOIN Currencies c ON LEFT(p.paytype,1) = c.POSCurrency
WHERE r.trsdate >= '''+ convert(varchar(10), @startDate, 101) +''' AND r.trsdate <= '''+ convert(varchar(10), @endDate, 101) +''' 
) p
pivot
(sum(amount) FOR CurrencyDesc in('+@cols+')) piv'
execute(@query)

select * from ##tempz

1 个答案:

答案 0 :(得分:2)

您没有指定您正在使用的RDBMS,但我假设SQL Server基于您之前的问题。根据有限的详细信息,您可以PIVOT数据。

如果您提前知道这些值,则可以使用静态数据透视表对值进行硬编码:

select *
from
(
    select 
        cast(r.trsdate as DATE) date,
        c.CurrencyDesc,
        p.amount
    from rpPay p
    left join RPTrs r
        on p.id = r.id
    left join Currencies c
        on p.PayType = c.PayType
    where r.trsdate >= @startDate 
        and r.trsdate <= @enddate
) src
pivot
(
    sum(amount)
    for CurrencyDesc in (Amex, Cash, Visa, Check, [Gift Card])
) piv

如果值未知,则可以使用动态sql:

declare @startDate datetime
declare @enddate datetime
  set @startDate = '1/1/12'
 set @enddate = '1/1/13'
DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(c.CurrencyDesc) 
                    from rpPay p
                    left join RPTrs r
                        on p.id = r.id
                    left join Currencies c
                        on p.PayType = c.PayType
                    where r.trsdate >= @startDate 
                        and r.trsdate <= @enddate
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query 
    = 'select date, '+@cols+'
       from
       (
         select 
            cast(r.trsdate as DATE) date,
            c.CurrencyDesc,
            p.amount
        from rpPay p
        left join RPTrs r
            on p.id = r.id
        left join Currencies c
            on p.PayType = c.PayType
        where r.trsdate >= '''+ convert(varchar(10), @startDate, 101) +'''
            and r.trsdate <= '''+ convert(varchar(10), @endDate, 101) +'''
       ) p
       pivot
       (
          sum(amount)
          for CurrencyDesc in('+@cols+')
       ) piv'

execute(@query)

编辑#1,根据您可以使用的编辑问题:

declare @startDate datetime
declare @enddate datetime
declare @registernum int
declare @storename int
declare @cashiername varchar(20)
set @startDate = '1/1/2012'
set @enddate = '1/1/2013'
set @registernum = 01
set @storename = '01'
set @cashiername = 'admin'

DECLARE @cols AS NVARCHAR(MAX),
    @colsNull AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(c.CurrencyDesc) 
                        from rpPay p 
                        left join RPTrs r 
                            on p.ReceiptNo = r.ReceiptNo 
                        left join Currencies c 
                            on p.PayType = c.POSCurrency
                        where r.trsdate >= @startDate and r.trsdate <= @enddate
                            and cashregister = @registernum
                            and r.storeid = @storename
                            and cashier = @cashiername
                        FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'),1,1,'')

select @colsNull = STUFF((SELECT DISTINCT ', IsNull(' + QUOTENAME(c.CurrencyDesc) +', 0) as '+ QUOTENAME(c.CurrencyDesc)
                        from rpPay p 
                        left join RPTrs r 
                            on p.ReceiptNo = r.ReceiptNo 
                        left join Currencies c 
                            on p.PayType = c.POSCurrency
                        where r.trsdate >= @startDate and r.trsdate <= @enddate
                            and cashregister = @registernum
                            and r.storeid = @storename
                            and cashier = @cashiername
                        FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'),1,1,'')

--select @cols, @colsnull

set @query = 'select date, cashregister, storeid, cashier, '+@colsNull+'
                from
                (
                    select cast(r.trsdate as DATE) date,
                        c.CurrencyDesc,
                        p.amount,
                        r.cashregister,
                        r.storeid,
                        r.cashier 
                    from rpPay p 
                    left join RPTrs r 
                        on p.ReceiptNo = r.receiptno 
                    left join Currencies c 
                        on p.PayType = c.POSCurrency
                    where r.trsdate >= '''+ convert(varchar(10), @startDate, 101) +''' 
                        and r.trsdate <= '''+ convert(varchar(10), @endDate, 101) +''' 
                        and cashregister = '''+cast(@registernum as varchar(10))+''' 
                        and r.storeid = '''+cast(@storename as varchar(50))+''' 
                        and r.cashier = '''+@cashiername+''' 
                ) p
                pivot
                (
                    sum(amount) 
                    for CurrencyDesc in('+@cols+')
                ) piv'

execute(@query)

请参阅SQL Fiddle with Demo