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

问题描述 投票:2回答:2

编辑: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。是否有一些带有函数的怪癖会导致计数返回一个不同于实际行数的值?

sql sql-server tsql sql-server-2008-r2
2个回答
0
投票

这是JetBrain的DataGrip产品的一个问题。当我在SSMS中运行相同的代码时,它返回了COUNT的适当数量。


0
投票

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

如果它被清除,那么count(*)将其行数从索引而不是表中拉出,而select返回实际的行。

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

© www.soinside.com 2019 - 2024. All rights reserved.