SQL Server-PIVOT表到每个日期一列

时间:2018-09-07 16:10:10

标签: sql sql-server

我当前正在将MS Access数据库移至SQL Server。我有一个cross-tab query,我需要转换为Pivot table

Pivot table将位于sproc中,为monthyear提供参数。这些参数放在WHERE的{​​{1}}子句中。

到目前为止,

SQL:

subquery

我在SELECT IDNbr, [Name] FROM (SELECT a1.IDNbr , a2.[CustName] as [Name] , a1.BalDate, a1.Balance FROM IDTable a1 INNER JOIN CustTable a2 ON (a1.IDNbr = a2.IDNbr) WHERE MONTH(a1.BalDate) = @month AND YEAR(a1.BalDate) = @year) as d1 PIVOT ( SUM(Balance) For Balance in ([BalDate]) --Error: see below ) piv; 部分遇到的错误是:

  

PIVOT运算符中指定的列名称“ BalDate”与PIVOT参数中的现有列名称冲突。

我也收到错误消息:

  

为“ piv”指定了“ BalDate”列。

当前数据:

Pivot

所需数据:

Customer  |   BalDate   | Balance
----------+-------------+--------
Customer1 |  1/01/2017  | 0.00
Customer1 |  1/02/2017  | 0.00
Customer1 |  1/03/2017  | 0.00
Customer1 |  1/04/2017  | 0.00
....      |  ....       | ....

主要问题:我该如何纠正| Customer | 01/01/2017 | 01/02/2017 | 01/03/2017 | 01/04/2017 | 01/05/2017 | 01/06/2017 | 01/07/2017 | 01/08/2017 | 01/09/2017 | 01/10/2017 | .... +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | Customer1 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | .... | Customer2 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | .... | Customer3 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | .... 中的错误?

次要问题:我如何将Pivot Table提升到Current data

我仍然是SQL和SQL Server的初学者,所以如果答案很明显,我深表歉意。

在此先感谢您的帮助和建议!而且,我将很乐意尝试澄清任何似乎令人困惑或不清楚的内容!


我引用过的帖子,并试图将其应用于我的情况:

SQL Pivot Multiple Columns

Column name specified in the pivot operator conflicts

Column was specified multiple times

How to Create A CrossTab query

SQL Server Pivot Column Data

3 个答案:

答案 0 :(得分:1)

在MS Sql Server中,您需要为此使用动态sql。

首先使用日期计算一个变量。
然后将其用于动态查询的字符串中。

您可以在{em> rextester 上对其进行here测试

DECLARE @Dates NVARCHAR(max);

SELECT @Dates = CONCAT(@Dates + ', ', QUOTENAME(BalDate)) 
FROM IDTable
WHERE YEAR(BalDate) = @year
  AND MONTH(BalDate) = @month 
GROUP BY BalDate
ORDER BY BalDate;

DECLARE @DynSql NVARCHAR(max); 
SET @DynSql = 'SELECT *
FROM
(
  SELECT a1.IDNbr, a2.[CustName] as [Name], a1.BalDate, a1.Balance 
  FROM IDTable a1 
  INNER JOIN CustTable a2 ON (a1.IDNbr = a2.IDNbr)
  WHERE MONTH(a1.BalDate) = @month 
  AND YEAR(a1.BalDate) = @year
) as src
PIVOT (
  SUM(Balance) 
  FOR BalDate IN ('+ @Dates +') 
) pvt';

DECLARE @Params NVARCHAR(500) = N'@year INT, @month INT';  

-- SELECT @DynSql AS DynSql;
EXECUTE sp_executesql @DynSql, @Params, @year = @year, @month = @month;

答案 1 :(得分:1)

您可以尝试对BalDate使用动态SQL。

由于查询具有参数,因此您可以尝试使用sp_executesql并在执行语法中附加参数。

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

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(a1.BalDate) 
            FROM IDTable a1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')



set @query = 'SELECT *
FROM (
    SELECT a1.IDNbr , a2.[CustName] as [Name] , a1.BalDate, a1.Balance 
    FROM IDTable a1 INNER JOIN CustTable a2 ON (a1.IDNbr = a2.IDNbr)
    WHERE MONTH(a1.BalDate) = @month AND YEAR(a1.BalDate) = @year
) as d1
PIVOT (
    SUM(Balance)
    For Balance in ('+ @cols +') --Error: see below
) piv'


EXECUTE sp_executesql @query, N'@year INT,@month INT', 
                    @year = @year,
                    @month = @month

答案 2 :(得分:1)

听起来像是需要动态枢轴,

首先,您必须选择要在数据透视表中使用的所有日期, 日期必须为QuoteName格式,即[Date],否则枢轴将无法理解。

DECLARE @Days NVarchar(MAX)
SEt @Days = STUFF((SELECT ',' + QUOTENAME(a1.BalDate) 
                    FROM IDTable a1
                    group by a1.BalDate
                    order by a1.BalDate
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
Select @Days

然后,您必须构建一个动态枢纽,像这样。

DECLARE @FinalQuery NVARCHAR (MAX)
SET @FinalQuery =   'SELECT *
                     INTO #ToReportOn
                     FROM
                         (SELECT a1.IDNbr , a2.[CustName] as [Name] , a1.BalDate, a1.Balance 
                          FROM IDTable a1 INNER JOIN CustTable a2 ON (a1.IDNbr = a2.IDNbr)
                          WHERE MONTH(a1.BalDate) = @month AND YEAR(a1.BalDate) = @year) as d1
                         ) A
            PIVOT
                  (
                    SUM(Balance)
                   For BalDate in ('+@Days +')
                  ) B
ORDER BY document_group

SELECT * FROM #ToReportOn 
'
--EXECUTE(@FinalQuery)
PRINT @FinalQuery

我没有测试。但是我认为动态枢纽是解决您的问题的方法。