SQL Server每个月都会获得销售额

时间:2014-05-20 11:18:35

标签: sql sql-server

我需要一个SQL查询来获取每个月的所有销售额,但如果没有销售额,那么说第3个月应该显示为0。

我目前有这个SQL:

DECLARE @From date
DECLARE @To date
DECLARE @StyleID int
DECLARE @CustomerID int
DECLARE @ColorID int
DECLARE @ClientID int
DECLARE @DataTypeID INT

SET @ColorID = 102
SET @DataTypeID = 3

SELECT
    Months.MonthNr,
    CONCAT(Months.MonthName_EN,' ',YEAR(Orders.Created)) AS WeekBegining
    ,DataTypes.DataType 
    ,SUM(XS_1218) as XS_1218
    ,SUM(S_23) as S_23
    ,SUM(M_45) as M_45
    ,SUM(L_67) as L_67
    ,SUM(XL_811) as XL_811
    ,SUM(XXL) as XXL
    ,SUM([1Size]) as [1Size]
    ,SUM(XS_1218)+SUM(S_23)+SUM(M_45)+SUM(L_67)+SUM(XL_811)+SUM(XXL)+SUM([1Size]) as Total
FROM 
    OrdersData
LEFT JOIN 
    DataTypes ON DataTypes.ID = DataTypeID 
LEFT JOIN 
    Orders ON Orders.ID = OrdersID
LEFT JOIN 
    Months ON Months.MonthNr = MONTH(Orders.Created)
WHERE 
    (((@From is null) OR (@To is null)) OR (Orders.Created BETWEEN @From AND @To)) AND -- Period Filter
    ((@StyleID is null) OR (@StyleID = OrdersData.StyleID)) AND -- Style Filter
    ((@CustomerID is null) OR (@CustomerID = OrdersData.CustomerID)) AND -- Customer Filter
    ((@ColorID is null) OR (@ColorID = OrdersData.ColorID)) AND -- Color Filter
    ((@ClientID is null) OR (@ClientID = Orders.ClientID)) AND -- Client Filter
    ((@DataTypeID is null) OR (@DataTypeID = OrdersData.DataTypeID)) AND
    YEAR(Orders.Created) = 2013
GROUP BY 
    DataTypes.DataType, YEAR(Orders.Created), MONTH(Orders.Created), 
    Months.MonthNr, Months.MonthName_EN --DataTypes.DataType
ORDER BY 
    DataTypes.DataType, YEAR(Orders.Created), MONTH(Orders.Created),
    Months.MonthNr, Months.MonthName_EN ASC

,结果如下:

enter image description here

我需要1,2,3个月全部为0

感谢GarethD只是编辑你的代码它有几个错误:) 溶剂:

脚本:

DECLARE @From date
DECLARE @To date
DECLARE @StyleID int
DECLARE @CustomerID int
DECLARE @ColorID int
DECLARE @ClientID int
DECLARE @DataTypeID INT

SET @ColorID = 102
SET @DataTypeID = 3
SET @From = '2013-01-01'
SET @To = '2014-12-01'

;WITH Data AS
(   SELECT  MONTH(Orders.Created) AS MonthCreated
            ,YEAR(Orders.Created) AS YearCreated
            ,SUM(XS_1218) as XS_1218
            ,SUM(S_23) as S_23
            ,SUM(M_45) as M_45
            ,SUM(L_67) as L_67
            ,SUM(XL_811) as XL_811
            ,SUM(XXL) as XXL
            ,SUM([1Size]) as [1Size]
            ,SUM(XS_1218)+SUM(S_23)+SUM(M_45)+SUM(L_67)+SUM(XL_811)+SUM(XXL)+SUM([1Size]) AS Total
    FROM    OrdersData
            LEFT JOIN DataTypes 
                ON DataTypes.ID = DataTypeID 
            LEFT JOIN Orders 
                ON Orders.ID = OrdersID
    WHERE 
    (((@From is null) OR (@To is null)) OR (Orders.Created BETWEEN @From AND @To)) AND -- Period Filter
    ((@StyleID is null) OR (@StyleID = OrdersData.StyleID)) AND -- Style Filter
    ((@CustomerID is null) OR (@CustomerID = OrdersData.CustomerID)) AND -- Customer Filter
    ((@ColorID is null) OR (@ColorID = OrdersData.ColorID)) AND -- Color Filter
    ((@ClientID is null) OR (@ClientID = Orders.ClientID)) AND -- Client Filter
    ((@DataTypeID is null) OR (@DataTypeID = OrdersData.DataTypeID))
    GROUP BY YEAR(Orders.Created),MONTH(Orders.Created) --DataTypes.DataType
)
SELECT  m.MonthNr,
        m.MonthYear,
        WeekBegining = CONCAT(m.MonthName_EN,' ',ISNULL(YearCreated,MonthYear)),
        XS_1218 = ISNULL(d.XS_1218, 0),
        S_23 = ISNULL(d.S_23, 0),
        M_45 = ISNULL(d.M_45, 0),
        L_67 = ISNULL(d.L_67, 0),
        XL_811 = ISNULL(d.XL_811, 0),
        XXL = ISNULL(d.XXL, 0),
        [1Size] = ISNULL(d.[1Size], 0),
        Total = ISNULL(d.Total, 0)
FROM    Months AS m
        LEFT JOIN Data AS d
            ON d.MonthCreated = m.MonthNr AND d.YearCreated = m.MonthYear
WHERE m.MonthYear BETWEEN YEAR(@From) AND YEAR(@To)
ORDER BY m.MonthYear,m.MonthNr

月份表:

CREATE TABLE [dbo].[Months](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [MonthNr] [int] NOT NULL,
    [MonthName_EN] [nvarchar](150) NOT NULL,
    [MonthYear] [int] NOT NULL,
 CONSTRAINT [PK_Months] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

使用值填充月表,它就像魅力一样

结果: enter image description here

希望这有助于某人

2 个答案:

答案 0 :(得分:1)

您应该将FROM子句与MonthsLEFT JOIN一起启动到其他表格。 像下面这样的东西?

--previous code
FROM Months
LEFT JOIN Orders ON Months.MonthNr = MONTH(Orders.Created)
LEFT JOIN DataTypes ON Orders.ID = OrdersID
LEFT JOIN OrdersData ON DataTypes.ID = DataTypeID 
--next code

答案 1 :(得分:1)

看起来您需要从Months表格中进行选择,然后选择加入数据,而不是相反,

WITH Data AS
(   SELECT  MONTH(Orders.Created) AS MonthCreated
            ,DataTypes.DataType 
            ,SUM(XS_1218) as XS_1218
            ,SUM(S_23) as S_23
            ,SUM(M_45) as M_45
            ,SUM(L_67) as L_67
            ,SUM(XL_811) as XL_811
            ,SUM(XXL) as XXL
            ,SUM([1Size]) as [1Size]
            ,SUM(XS_1218)+SUM(S_23)+SUM(M_45)+SUM(L_67)+SUM(XL_811)+SUM(XXL)+SUM([1Size]) AS Total
    FROM    OrdersData
            LEFT JOIN DataTypes 
                ON DataTypes.ID = DataTypeID 
            LEFT JOIN Orders 
                ON Orders.ID = OrdersID
    WHERE 
    (((@From is null) OR (@To is null)) OR (Orders.Created BETWEEN @From AND @To)) AND -- Period Filter
    ((@StyleID is null) OR (@StyleID = OrdersData.StyleID)) AND -- Style Filter
    ((@CustomerID is null) OR (@CustomerID = OrdersData.CustomerID)) AND -- Customer Filter
    ((@ColorID is null) OR (@ColorID = OrdersData.ColorID)) AND -- Color Filter
    ((@ClientID is null) OR (@ClientID = Orders.ClientID)) AND -- Client Filter
    ((@DataTypeID is null) OR (@DataTypeID = OrdersData.DataTypeID)) AND
    Orders.Created >= '20130101' AND
    Orders.Created < '20140101'
    GROUP BY DataTypes.DataType,MONTH(Orders.Created) --DataTypes.DataType
)
SELECT  Months.MonthNr,
        WeekBegining = CONCAT(Months.MonthName_EN,' ',YEAR(Orders.Created)),
        XS_1218 = ISNULL(d.XS_1218, 0),
        S_23 = ISNULL(d.S_23, 0),
        M_45 = ISNULL(d.M_45, 0),
        L_67 = ISNULL(d.XS_L_671218, 0),
        XL_811 = ISNULL(d.XL_811, 0),
        XXL = ISNULL(d.XXL, 0),
        [1Size] = ISNULL(d.[1Size], 0),
        Total = ISNULL(d.Total, 0)
FROM    Months AS m
        LEFT JOIN Data AS d
            ON d.CreatedMonth = m.MonthNr;

这样,即使没有订单数据,您也会显示月份。

注意,我已更改此行:

YEAR(Orders.Created) = 2013

Orders.Created >= '20130101' AND
Orders.Created < '20140101'

后者为sargable,可以利用Created列上的索引,而后者则不会,也不会。

此外,它取决于您实际调用此查询的方式,但您可能需要考虑使用OPTION (RECOMPILE),这可能允许更好的执行计划,查询将在运行时编译,并且谓词如下:

(@DataTypeID is null) OR (@DataTypeID = OrdersData.DataTypeID)

可以评估您传递的@DataTypeID的具体值。如果没有这个,你总会得到一个表扫描,而有了它,你可能会在@DataTypeID不为空的时候找到索引搜索。