6

我有一个存储过程,它从一个表中获取数据,运行我的动态数据透视存储过程,然后输出到页面中。问题是,有大量的空条目。当我在页面上处理这些数据时,我需要添加每个 TerminalID 的每个燃料数量。当它遇到空条目时会出现问题。我不想让程序读取每一行和每一列以将 null 转换为 0,并且希望在 SP 中这样做。

对于测试,我制作了这个脚本:

DECLARE @QUERY NVARCHAR(MAX)
    ,   @Soucecolumn VARCHAR(MAX)
    ,   @BeginningDate VARCHAR(MAX)
    ,   @EndingDate VARCHAR(MAX)
    ,   @CompanyID VARCHAR(2)

SET NOCOUNT ON;

SET @BeginningDate = CONVERT(VARCHAR(30), CAST('2004-01-01' AS DATE));
SET @EndingDate = CONVERT(VARCHAR(30), CAST('2007-01-01' AS DATE));
SET @CompanyID = CONVERT(INT, '2');
SET @Soucecolumn = STUFF((
    SELECT DISTINCT ', \[' + CAST(FuelTypeID AS VARCHAR(4)) + '\]'
    FROM tt_Manifest_Fuel_Distribution
    FOR XML PATH ('')), 1, 1, '')

SET @QUERY = '(
SELECT ManifestID, TerminalID, ' + @Soucecolumn + ' 
FROM (
    SELECT mfd.ManifestID, m.TerminalID, mfd.FuelTypeID, mfd.FuelQuantity 
    FROM tt_Manifest_Fuel_Distribution mfd, tt_Terminals t, tt_Fuel_Types ft, tt_Manifests m
    WHERE mfd.FuelTypeID=ft.FuelTypeID
        AND m.ManifestID=mfd.ManifestID
        AND m.CompanyID= ' + @CompanyID + ' 
        AND m.ManifestInsertDate BETWEEN ''' + @BeginningDate + ''' AND ''' + @EndingDate +
        ''' 
) up 
PIVOT (
    MAX(FuelQuantity) FOR \[FuelTypeID\] IN (' + @Soucecolumn + ')
) AS pvt)'

EXEC sp_executesql @QUERY

样本数据为:

>ManifestID   TerminalID   3   6   4   2   1   5
>417    1   NULL    NULL    NULL    NULL    NULL    2478
>421    1   NULL    NULL    NULL    NULL    3458    NULL
>508    1   NULL    NULL    NULL    NULL    NULL    2471
>826    1   NULL    NULL    NULL    NULL    NULL    7464
>832    1   NULL    NULL    NULL    NULL    3482    NULL
>833    1   1001    NULL    NULL    NULL    1492    NULL
>844    1   NULL    NULL    NULL    NULL    2498    NULL
>870    1   NULL    NULL    NULL    NULL    5991    2503
>872    1   NULL    NULL    NULL    NULL    3494    NULL
>2      2   NULL    NULL    5514    NULL    NULL    2505
>43     2   NULL    NULL    NULL    NULL    7011    NULL
>46     2   1005    NULL    NULL    NULL    5007    2510
>60     2   NULL    NULL    3502    NULL    NULL    4513
>63     2   NULL    NULL    4505    NULL    NULL    3008
>69     2   NULL    NULL    4008    NULL    4508    NULL
>78     2   1007    NULL    NULL    NULL    5022    NULL
>79     2   NULL    NULL    2505    NULL    NULL    NULL

我尝试在 mfd.FuelQuantity 和 @Sourcecolumn 周围放置 ISNULL(,0)。mfd.FuelQuantiity 似乎没有变化,而 @Sourcecolumn 错误地声称 ISNull() 需要 2 个参数。

我是否以错误的方式看待这个问题?

4

2 回答 2

3

我强烈建议远离已弃用的隐式连接。

您需要将子句列表中的ISNULL()每个项目合并到其中。它引发错误的原因是因为您的整个列列表都包含在一个语句中: 您需要@sourcecolumnSELECTISNULL(col1,col2,col3...,0)ISNULL(col1,0),ISNULL(col2,0)...

我建议制作一个单独的 sourcecolumn 变量以在您的SELECT.

就像是:

SET @Sourcecolumn2 = STUFF((SELECT distinct ',ISNULL(\[' + CAST(FuelTypeID as varchar(4)) + ',0)\]as '+ CAST(FuelTypeID as varchar(4)) +'     FROM tt_Manifest_Fuel_Distribution
FOR XML PATH('')),1,1,'') 

所以最终:

![Declare    @QUERY NVARCHAR(MAX), 
@Soucecolumn VARCHAR(MAX),
@Sourcecolumn2 VARCHAR(MAX),
@BeginningDate VARCHAR(MAX),
@EndingDate VARCHAR(MAX),
@CompanyID VARCHAR(2)
SET NOCOUNT ON;
SET @BeginningDate = convert(varchar(30), cast('2004-01-01' as date));
SET @EndingDate = convert(varchar(30), cast('2007-01-01' as date));
SET @CompanyID = convert(int, '2');
SET @Soucecolumn = STUFF((SELECT distinct ', \[' + CAST(FuelTypeID as varchar(4)) + '\]'     FROM tt_Manifest_Fuel_Distribution
FOR XML PATH('')),1,1,''); 
SET @Sourcecolumn2 = STUFF((SELECT distinct ',ISNULL(\[' + CAST(FuelTypeID as varchar(4)) + ',0)\] as '+ CAST(FuelTypeID as varchar(4))+'     FROM tt_Manifest_Fuel_Distribution
FOR XML PATH('')),1,1,''); 
SET @QUERY = '(SELECT ManifestID, TerminalID, ' + @Sourcecolumn2 + ' FROM (
SELECT mfd.ManifestID, m.TerminalID, mfd.FuelTypeID, mfd.FuelQuantity 
FROM tt_Manifest_Fuel_Distribution mfd, tt_Terminals t, tt_Fuel_Types ft, tt_Manifests m
WHERE mfd.FuelTypeID=ft.FuelTypeID
AND m.ManifestID=mfd.ManifestID
AND m.CompanyID= ' + @CompanyID + ' 
AND m.ManifestInsertDate BETWEEN ''' + @BeginningDate + ''' AND ''' + @EndingDate + 
''' ) up PIVOT (MAX(FuelQuantity) FOR \[FuelTypeID\] IN (' + @Soucecolumn + ')) AS pvt)'
exec sp_executesql  @QUERY][1]
于 2013-09-02T15:34:41.180 回答
1

考虑下表

在此处输入图像描述

这是示例数据

SELECT * INTO #TEMP
FROM
(
    SELECT '01/JAN/2014' [DATE],'A' NAME,100 MARKS
    UNION ALL
    SELECT '02/JAN/2014' [DATE],'A' NAME,120
    UNION ALL
    SELECT '02/JAN/2014' [DATE],'B' NAME,130
    UNION ALL
    SELECT '03/JAN/2014' [DATE],'B' NAME,115
    UNION ALL
    SELECT '01/JAN/2014' [DATE],'C' NAME,123
    UNION ALL
    SELECT '01/JAN/2014' [DATE],'C' NAME,134
    UNION ALL
    SELECT '03/JAN/2014' [DATE],'C' NAME,146
    UNION ALL
    SELECT '04/JAN/2014' [DATE],'C' NAME,149
)TAB

现在为枢轴选择不同的名称

DECLARE @cols NVARCHAR (MAX)
SET @cols = SUBSTRING((SELECT DISTINCT ',['+NAME+']' 
FROM #TEMP GROUP BY NAME FOR XML PATH('')),2,8000)

现在您需要另一个变量来应用NULL to zero逻辑

DECLARE @NulltoZeroCols NVARCHAR (MAX)
SET @NulltoZeroCols = SUBSTRING((SELECT DISTINCT ',ISNULL(['+NAME+'],0) AS ['+NAME+']' 
FROM #TEMP GROUP BY NAME FOR XML PATH('')),2,8000)

现在使用两个变量旋转查询

DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT DATE,' + @NulltoZeroCols + ' FROM 
             (
                 SELECT [DATE],NAME,MARKS FROM #TEMP
             ) x
             PIVOT 
             (
                 SUM(MARKS)
                 FOR [NAME] IN (' + @cols + ')
            ) p
            ;'
EXEC SP_EXECUTESQL @query

最后你的结果如下

在此处输入图像描述

于 2014-12-08T10:38:31.933 回答