COUNTing函数输出返回的值与直接运行经过稍微修改的SQL的返回值不同

时间:2019-02-28 22:21:17

标签: sql sql-server tsql sql-server-2008-r2

编辑:DB是SQL Server 2008R2

所以,本质上,我遇到了一个问题,其中#行!= count(*)。运行此代码:

SELECT *
FROM Fn_ForecastReport_TEST(NULL)

返回519行输出。但是,运行以下代码:

SELECT COUNT(*)
FROM Fn_ForecastReport_TEST(NULL)

返回502。这非常令人困惑,所以我使用了该函数的代码:

CREATE FUNCTION dbo.Fn_ForecastReport_TEST(@Date DATE = NULL)
RETURNS @ForecastReportTable TABLE
(
  InvcLine_SM    NVARCHAR(155),
  Cust_No        NVARCHAR(15),
  Cust_Name      NVARCHAR(100),
  Genus          NVARCHAR(20),
  S_City         NVARCHAR(100),
  [Default Whs]  NVARCHAR(30),
  U_CustChannel  NVARCHAR(20),
  [ActualKits-2] NUMERIC(38, 17),
  [ActualKits-1] NUMERIC(38, 17),
  ActualKits     NUMERIC(38, 17),
  [FC Kits]      INT,
  [FC Kits+1]    INT,
  [FC Kits+2]    INT,
  [FC Sales]     NUMERIC(38, 6),
  [FC Sales+1]   NUMERIC(38, 6),
  [FC Sales+2]   NUMERIC(38, 6),
  [Avg Price]    NUMERIC(38, 6)
)
AS
BEGIN
  -- If we provide NULL to the function, it will use today's date
  SET @Date = ISNULL(@Date, GETDATE());

  DECLARE
    @TPlus2EndDate AS DATE,
    @TPlus2StartDate AS DATE,
    @TPlus1EndDate AS DATE,
    @TPlus1StartDate AS DATE,
    @TMinus0EndDate AS DATE,
    @TMinus0StartDate AS DATE,
    @TMinus1EndDate AS DATE,
    @TMinus1StartDate AS DATE,
    @TMinus2EndDate AS DATE,
    @TMinus2StartDate AS DATE;

  -- We use T Minus 0 as the basis for all other calculations so it needs to be calculated first
  SELECT @TMinus0StartDate = FirstDay,
         @TMinus0EndDate   = LastDay
  FROM Fn_GetFirstAndLastDaysOfMonthFromDate(@Date);

  SELECT @TPlus2StartDate = FirstDay,
         @TPlus2EndDate   = LastDay
  FROM Fn_GetFirstAndLastDaysOfMonthFromDate(DATEADD(MONTH, 2, @TMinus0StartDate));

  SELECT @TPlus1StartDate = FirstDay,
         @TPlus1EndDate   = LastDay
  FROM Fn_GetFirstAndLastDaysOfMonthFromDate(DATEADD(MONTH, 1, @TMinus0StartDate));

  SELECT @TMinus1StartDate = FirstDay,
         @TMinus1EndDate   = LastDay
  FROM Fn_GetFirstAndLastDaysOfMonthFromDate(DATEADD(MONTH, -1, @TMinus0StartDate));

  SELECT @TMinus2StartDate = FirstDay,
         @TMinus2EndDate   = LastDay
  FROM Fn_GetFirstAndLastDaysOfMonthFromDate(DATEADD(MONTH, -2, @TMinus0StartDate));

  WITH Genera_CTE (Genus) AS (
    SELECT '106' UNION ALL
    SELECT '108' UNION ALL
    SELECT '108YM' UNION ALL
    SELECT '112' UNION ALL
    SELECT '112XC' UNION ALL
    SELECT '118'
  ),

  SpecificPricesForEachBusinessPartnerByProductGenus AS (
    SELECT T0.cardcode,
           T1.U_Genus_Code,
           sum((T1.U_NETcontents + 551) * T0.price) [Price]
    FROM OSPP T0
    INNER JOIN OITM T1 ON T0.ItemCode = T1.ItemCode
    WHERE T0.price < 100
      AND T1.U_Netcontents BETWEEN 450 AND 552
      AND T1.Onhand <> 0
      AND T1.U_Genus_Code IN (SELECT Genus FROM Genera_CTE)
    GROUP BY T0.cardcode,
             T1.U_Genus_Code
  ),

  BestWarehouseForBusinessPartnerCity_CTE AS (
    SELECT CardCode,
           City,
           U_Default_Whs
    FROM CRD1
    WHERE AdresType = 'S'
      AND U_Default_Whs IS NOT NULL
    GROUP BY CardCode,
             City,
             U_Default_Whs
  ),

  MostRecentForecastsForPeriod AS (
    SELECT *
    FROM Fn_GetMostRecentForecastsForMonthOfDate(@Date)

    UNION ALL

    SELECT *
    FROM Fn_GetMostRecentForecastsForMonthOfDate(@TPlus1StartDate)

    UNION ALL

    SELECT *
    FROM Fn_GetMostRecentForecastsForMonthOfDate(@TPlus2StartDate)
  ),

  ForecastsReformattedForReport AS (
    SELECT T1.SlpName,
           T0.U_Cust_ID,
           T2.CardName,
           T0.U_Genus,
           T0.U_Ship_City,
           ''                [Dfl Whs],
           T2.U_CustChannel  [U_CustChannel],
           0                 [ActualKits],
           0                 [ActualKits-1],
           0                 [ActualKits-2],
           SUM(CASE
                 WHEN T0.U_FC_Month BETWEEN @TMinus0StartDate AND @TMinus0EndDate
                 THEN T0.U_Sets
                 ELSE 0
           END) [Forecast],
           SUM(CASE
                 WHEN T0.U_FC_Month BETWEEN @TPlus1StartDate AND @TPlus1EndDate
                 THEN T0.U_Sets
                 ELSE 0
           END) [Forecast+1],
           SUM(CASE
                 WHEN T0.U_FC_Month BETWEEN @TPlus2StartDate AND @TPlus2EndDate
                 THEN T0.U_Sets
                 ELSE 0
           END) [Forecast+2]
    FROM MostRecentForecastsForPeriod T0
    INNER JOIN OSLP T1 ON T0.U_SLP_ID = T1.SlpCode
    INNER JOIN OCRD T2 ON T0.U_Cust_ID = T2.CardCode
    WHERE T0.U_FC_Month BETWEEN @TMinus0StartDate AND @TPlus2EndDate
    GROUP BY T1.SlpName,
             T0.U_Cust_ID,
             T2.CardName,
             T0.U_Genus,
             T0.U_Ship_City,
             T2.U_CustChannel
  ),

  ActualTransactionsFormattedForReport AS (
    SELECT InvcLine_SM,
           Cust_No,
           Cust_Name,
           Genus,
           S_City,
           CASE
             WHEN U_Default_Whs IS NULL THEN 'Mesa Dflt'
             ELSE U_Default_Whs
           END AS 'Default Whs',
           U_CustChannel,
           SUM(CASE
                 WHEN Trx_Date BETWEEN @TMinus0StartDate AND @TMinus0EndDate
                 THEN Kits
                 ELSE 0
           END) [ActualKits],
           SUM(CASE
                 WHEN Trx_Date BETWEEN @TMinus1StartDate AND @TMinus1EndDate
                 THEN Kits
                 ELSE 0
           END) [ActualKits-1],
           SUM(CASE
                 WHEN Trx_Date BETWEEN @TMinus2StartDate AND @TMinus2EndDate
                 THEN Kits
                 ELSE 0
           END) [ActualKits-2],
           0 [Forecast],
           0 [Forecast+1],
           0 [Forecast+2]
    FROM SWD_SALES_TRX
    WHERE Genus IN (SELECT Genus FROM Genera_CTE)
      AND Trx_Date BETWEEN @TMinus2StartDate AND @TMinus0EndDate
    GROUP BY InvcLine_SM,
             cust_no,
             Cust_name,
             U_Default_Whs,
             Genus,
             S_City,
             U_CustChannel
  ),

  TransactionsAndForecastsMergedForReport AS (
    SELECT *
    FROM ActualTransactionsFormattedForReport

    UNION ALL

    SELECT *
    FROM ForecastsReformattedForReport
  )

  INSERT @ForecastReportTable
  SELECT
        T0.InvcLine_SM,
        T0.Cust_No,
        T0.Cust_Name,
        T0.Genus,
        T0.S_City,
        CASE
          WHEN MAX(A0.U_Default_Whs) = ''
            OR MAX(A0.U_Default_Whs) IS NULL
          THEN 'Mesa Dflt'
          ELSE MAX(A0.U_Default_Whs)
        END                                               [Default Whs],
        T0.U_CustChannel,
        SUM(T0.[ActualKits-2])                            [ActualKits-2],
        SUM(T0.[ActualKits-1])                            [ActualKits-1],
        SUM(T0.[ActualKits])                              [ActualKits],
        Sum(T0.[Forecast])                                [FC Kits],
        Sum(T0.[Forecast+1])                              [FC Kits+1],
        Sum(T0.[Forecast+2])                              [FC Kits+2],
        SUM(T0.[Forecast]) * ISNULL(T5.Price, t6.total)   [FC Sales],
        SUM(T0.[Forecast+1]) * ISNULL(T5.Price, t6.total) [FC Sales+1],
        SUM(T0.[Forecast+2]) * ISNULL(T5.Price, t6.total) [FC Sales+2],
        MAX(T6.Total)                                     [Avg Price]
  FROM TransactionsAndForecastsMergedForReport T0
  LEFT JOIN SpecificPricesForEachBusinessPartnerByProductGenus T5 ON T0.Cust_No = T5.CardCode
                                                                 AND T5.U_Genus_Code = T0.Genus
  LEFT JOIN (
    SELECT T2.U_CustChannel,
           T1.U_Genus_Code,
           (CASE
             WHEN SUM(CASE
                        WHEN T1.[InvntryUom] <> 'KIT'
                        THEN T0.Quantity
                        ELSE T0.Quantity * ISNULL(T1.U_NetContents, 1)
                  END) = 0
             THEN 0
             ELSE sum(T0.LineTotal) / SUM(CASE
                                            WHEN T1.[InvntryUom] <> 'KIT'
                                            THEN T0.Quantity
                                            ELSE T0.Quantity * ISNULL(551 + T1.U_NetContents, 1)
                                      END)
           END) * (MAX(T1.U_NetContents) + 551) [Total]
    FROM (
      SELECT T0.CardCode,T1.LineTotal [LineTotal],T1.Quantity [Quantity],T1.ItemCode
      FROM OINV T0
      INNER JOIN INV1 T1 ON T0.DocEntry = T1.DocEntry
      WHERE T0.Canceled = 'N'
        AND (T1.LineTotal <> 0 OR TreeType = 'N')

      UNION ALL

      SELECT T0.CardCode,(T1.LineTotal) * -1 [LineTotal], -T1.Quantity [Quantity],T1.ItemCode
      FROM ORIN T0
      INNER JOIN RIN1 T1 ON T0.DocEntry = T1.DocEntry
      WHERE T0.Canceled = 'N'
        AND T0.docType <> 'S'
        AND T0.CANCELED = 'N'
        AND (T1.LineTotal <> 0 OR TreeType = 'N')
    ) T0
    INNER JOIN OITM T1 ON T0.ItemCode = T1.ItemCode
    INNER JOIN OCRD T2 ON T0.CardCode = T2.CardCode
    WHERE T1.U_Netcontents BETWEEN 450 AND 552
      AND t1.Onhand <> 0
      AND (
        T1.U_Genus_Code IN (SELECT Genus FROM Genera_CTE)
        OR (T1.[InvntryUom] = 'KIT' AND T1.U_Genus_Code = '108')
      )
    GROUP BY T2.U_CustChannel,
             T1.U_Genus_Code
  ) T6 ON T6.U_CustChannel = T0.U_CustChannel 
      AND T6.U_Genus_Code = T0.Genus
  LEFT JOIN BestWarehouseForBusinessPartnerCity_CTE A0 ON A0.CardCode = T0.Cust_No
                                                      AND LOWER(A0.City) = LOWER(T0.S_City)
  GROUP BY InvcLine_SM,
           cust_no,
           Cust_name,
           genus,
           S_City,
           t5.price,
           t6.total,
           T0.U_CustChannel;

  RETURN;
END
GO

我稍微修改了此SQL,以便可以在函数外部运行它,并且我注意到一些非常奇怪的东西,那就是当我在函数外部运行它时,错误消失了:

-- If we provide NULL to the function, it will use today's date
DECLARE @Date DATE = GETDATE();

DECLARE
  @TPlus2EndDate AS DATE,
  @TPlus2StartDate AS DATE,
  @TPlus1EndDate AS DATE,
  @TPlus1StartDate AS DATE,
  @TMinus0EndDate AS DATE,
  @TMinus0StartDate AS DATE,
  @TMinus1EndDate AS DATE,
  @TMinus1StartDate AS DATE,
  @TMinus2EndDate AS DATE,
  @TMinus2StartDate AS DATE;

-- We use T Minus 0 as the basis for all other calculations so it needs to be calculated first
SELECT @TMinus0StartDate = FirstDay,
       @TMinus0EndDate   = LastDay
FROM Fn_GetFirstAndLastDaysOfMonthFromDate(@Date);

SELECT @TPlus2StartDate = FirstDay,
       @TPlus2EndDate   = LastDay
FROM Fn_GetFirstAndLastDaysOfMonthFromDate(DATEADD(MONTH, 2, @TMinus0StartDate));

SELECT @TPlus1StartDate = FirstDay,
       @TPlus1EndDate   = LastDay
FROM Fn_GetFirstAndLastDaysOfMonthFromDate(DATEADD(MONTH, 1, @TMinus0StartDate));

SELECT @TMinus1StartDate = FirstDay,
       @TMinus1EndDate   = LastDay
FROM Fn_GetFirstAndLastDaysOfMonthFromDate(DATEADD(MONTH, -1, @TMinus0StartDate));

SELECT @TMinus2StartDate = FirstDay,
       @TMinus2EndDate   = LastDay
FROM Fn_GetFirstAndLastDaysOfMonthFromDate(DATEADD(MONTH, -2, @TMinus0StartDate));

WITH Genera_CTE (Genus) AS (
  SELECT '106' UNION ALL
  SELECT '108' UNION ALL
  SELECT '108YM' UNION ALL
  SELECT '112' UNION ALL
  SELECT '112XC' UNION ALL
  SELECT '118'
),

SpecificPricesForEachBusinessPartnerByProductGenus AS (
  SELECT T0.cardcode,
         T1.U_Genus_Code,
         sum((T1.U_NETcontents + 551) * T0.price) [Price]
  FROM OSPP T0
  INNER JOIN OITM T1 ON T0.ItemCode = T1.ItemCode
  WHERE T0.price < 100
    AND T1.U_Netcontents BETWEEN 450 AND 552
    AND T1.Onhand <> 0
    AND T1.U_Genus_Code IN (SELECT Genus FROM Genera_CTE)
  GROUP BY T0.cardcode,
           T1.U_Genus_Code
),

BestWarehouseForBusinessPartnerCity_CTE AS (
  SELECT CardCode,
         City,
         U_Default_Whs
  FROM CRD1
  WHERE AdresType = 'S'
    AND U_Default_Whs IS NOT NULL
  GROUP BY CardCode,
           City,
           U_Default_Whs
),

MostRecentForecastsForPeriod AS (
  SELECT *
  FROM Fn_GetMostRecentForecastsForMonthOfDate(@Date)

  UNION ALL

  SELECT *
  FROM Fn_GetMostRecentForecastsForMonthOfDate(@TPlus1StartDate)

  UNION ALL

  SELECT *
  FROM Fn_GetMostRecentForecastsForMonthOfDate(@TPlus2StartDate)
),

ForecastsReformattedForReport AS (
  SELECT T1.SlpName,
         T0.U_Cust_ID,
         T2.CardName,
         T0.U_Genus,
         T0.U_Ship_City,
         ''                [Dfl Whs],
         T2.U_CustChannel  [U_CustChannel],
         0                 [ActualKits],
         0                 [ActualKits-1],
         0                 [ActualKits-2],
         SUM(CASE
               WHEN T0.U_FC_Month BETWEEN @TMinus0StartDate AND @TMinus0EndDate
               THEN T0.U_Sets
               ELSE 0
         END) [Forecast],
         SUM(CASE
               WHEN T0.U_FC_Month BETWEEN @TPlus1StartDate AND @TPlus1EndDate
               THEN T0.U_Sets
               ELSE 0
         END) [Forecast+1],
         SUM(CASE
               WHEN T0.U_FC_Month BETWEEN @TPlus2StartDate AND @TPlus2EndDate
               THEN T0.U_Sets
               ELSE 0
         END) [Forecast+2]
  FROM MostRecentForecastsForPeriod T0
  INNER JOIN OSLP T1 ON T0.U_SLP_ID = T1.SlpCode
  INNER JOIN OCRD T2 ON T0.U_Cust_ID = T2.CardCode
  WHERE T0.U_FC_Month BETWEEN @TMinus0StartDate AND @TPlus2EndDate
  GROUP BY T1.SlpName,
           T0.U_Cust_ID,
           T2.CardName,
           T0.U_Genus,
           T0.U_Ship_City,
           T2.U_CustChannel
),

ActualTransactionsFormattedForReport AS (
  SELECT InvcLine_SM,
         Cust_No,
         Cust_Name,
         Genus,
         S_City,
         CASE
           WHEN U_Default_Whs IS NULL THEN 'Mesa Dflt'
           ELSE U_Default_Whs
         END AS 'Default Whs',
         U_CustChannel,
         SUM(CASE
               WHEN Trx_Date BETWEEN @TMinus0StartDate AND @TMinus0EndDate
               THEN Kits
               ELSE 0
         END) [ActualKits],
         SUM(CASE
               WHEN Trx_Date BETWEEN @TMinus1StartDate AND @TMinus1EndDate
               THEN Kits
               ELSE 0
         END) [ActualKits-1],
         SUM(CASE
               WHEN Trx_Date BETWEEN @TMinus2StartDate AND @TMinus2EndDate
               THEN Kits
               ELSE 0
         END) [ActualKits-2],
         0 [Forecast],
         0 [Forecast+1],
         0 [Forecast+2]
  FROM SWD_SALES_TRX
  WHERE Genus IN (SELECT Genus FROM Genera_CTE)
    AND Trx_Date BETWEEN @TMinus2StartDate AND @TMinus0EndDate
  GROUP BY InvcLine_SM,
           cust_no,
           Cust_name,
           U_Default_Whs,
           Genus,
           S_City,
           U_CustChannel
),

TransactionsAndForecastsMergedForReport AS (
  SELECT *
  FROM ActualTransactionsFormattedForReport

  UNION ALL

  SELECT *
  FROM ForecastsReformattedForReport
),

FinalOutput AS (
  SELECT T0.InvcLine_SM,
         T0.Cust_No,
         T0.Cust_Name,
         T0.Genus,
         T0.S_City,
         CASE
           WHEN MAX(A0.U_Default_Whs) = ''
             OR MAX(A0.U_Default_Whs) IS NULL
             THEN 'Mesa Dflt'
           ELSE MAX(A0.U_Default_Whs)
           END                                             [Default Whs],
         T0.U_CustChannel,
         SUM(T0.[ActualKits-2])                            [ActualKits-2],
         SUM(T0.[ActualKits-1])                            [ActualKits-1],
         SUM(T0.[ActualKits])                              [ActualKits],
         Sum(T0.[Forecast])                                [FC Kits],
         Sum(T0.[Forecast+1])                              [FC Kits+1],
         Sum(T0.[Forecast+2])                              [FC Kits+2],
         SUM(T0.[Forecast]) * ISNULL(T5.Price, t6.total)   [FC Sales],
         SUM(T0.[Forecast+1]) * ISNULL(T5.Price, t6.total) [FC Sales+1],
         SUM(T0.[Forecast+2]) * ISNULL(T5.Price, t6.total) [FC Sales+2],
         MAX(T6.Total)                                     [Avg Price]
  FROM TransactionsAndForecastsMergedForReport T0
         LEFT JOIN SpecificPricesForEachBusinessPartnerByProductGenus T5 ON T0.Cust_No = T5.CardCode
    AND T5.U_Genus_Code = T0.Genus
         LEFT JOIN (
    SELECT T2.U_CustChannel,
           T1.U_Genus_Code,
           (CASE
              WHEN SUM(CASE
                         WHEN T1.[InvntryUom] <> 'KIT'
                           THEN T0.Quantity
                         ELSE T0.Quantity * ISNULL(T1.U_NetContents, 1)
                END) = 0
                THEN 0
              ELSE sum(T0.LineTotal) / SUM(CASE
                                             WHEN T1.[InvntryUom] <> 'KIT'
                                               THEN T0.Quantity
                                             ELSE T0.Quantity * ISNULL(551 + T1.U_NetContents, 1)
                END)
             END) * (MAX(T1.U_NetContents) + 551) [Total]
    FROM (
           SELECT T0.CardCode,T1.LineTotal [LineTotal],T1.Quantity [Quantity],T1.ItemCode
           FROM OINV T0
                  INNER JOIN INV1 T1 ON T0.DocEntry = T1.DocEntry
           WHERE T0.Canceled = 'N'
             AND (T1.LineTotal <> 0 OR TreeType = 'N')

           UNION ALL

           SELECT T0.CardCode,(T1.LineTotal) * -1 [LineTotal], -T1.Quantity [Quantity],T1.ItemCode
           FROM ORIN T0
                  INNER JOIN RIN1 T1 ON T0.DocEntry = T1.DocEntry
           WHERE T0.Canceled = 'N'
             AND T0.docType <> 'S'
             AND T0.CANCELED = 'N'
             AND (T1.LineTotal <> 0 OR TreeType = 'N')
         ) T0
           INNER JOIN OITM T1 ON T0.ItemCode = T1.ItemCode
           INNER JOIN OCRD T2 ON T0.CardCode = T2.CardCode
    WHERE T1.U_Netcontents BETWEEN 450 AND 552
      AND t1.Onhand <> 0
      AND (
        T1.U_Genus_Code IN (SELECT Genus FROM Genera_CTE)
        OR (T1.[InvntryUom] = 'KIT' AND T1.U_Genus_Code = '108')
      )
    GROUP BY T2.U_CustChannel,
             T1.U_Genus_Code
  ) T6 ON T6.U_CustChannel = T0.U_CustChannel
    AND T6.U_Genus_Code = T0.Genus
         LEFT JOIN BestWarehouseForBusinessPartnerCity_CTE A0 ON A0.CardCode = T0.Cust_No
    AND LOWER(A0.City) = LOWER(T0.S_City)
  GROUP BY InvcLine_SM,
           cust_no,
           Cust_name,
           genus,
           S_City,
           t5.price,
           t6.total,
           T0.U_CustChannel
)

SELECT count(*)
FROM FinalOutput;

本质上,唯一的变化是将@Date切换为DECLARE而不是SET,并删除了函数输出的INSERT。是否存在一些使函数返回的值与实际行数不同的函数的怪癖?

2 个答案:

答案 0 :(得分:0)

这是JetBrain的DataGrip产品的问题。当我在SSMS中运行相同的代码时,它为COUNT返回了正确的金额。

答案 1 :(得分:0)

SQL Server有时在sys.sysindexes表/视图中提供的信息不正确...试图更新索引和统计信息,并查看其是否仍然不匹配。

如果清除,则count(*)正在将其行计数从索引而不是表中移出,而select返回实际行。

nvm,jetbrain做到了!多么糟糕!