下面是一个存储过程,用于计算一个月内制作的小部件数量。如果没有制作任何小部件,则不会存在任何记录。
执行计划显示了INNER JOIN
M 和 A 表中的一个,在语句中我正在执行一个LEFT OUTER JOIN
.
我想计算一个时间范围内制作的小部件的数量,将其加入月表(1 月至 12 月),并将结果显示在 SSRS 报告中。加入是因为我无法COUNT
获取不存在的数据。目前我得到:
MonthName Widget Count
February 2
March 3
April 4
May 6
June 5
July 4
August 6
September 2
October 4
November 1
December 2
我希望在列表中包含没有制作小部件的月份。
这是代码:
DECLARE @OName varchar(50)
DECLARE @Start_Date DATE
DECLARE @End_Date DATE
SET @OName = 'John'
SET @Start_Date = '01/01/2012'
SET @End_Date = '12/31/2012'
SELECT M.[MonthName]
,COUNT(A.[Widget_ID]) AS 'Widget Count'
FROM [Connector].dbo.[Months] AS M
LEFT OUTER JOIN [SERVER].[DATABASE].[dbo].[Widget] AS A
ON MONTH(A.[Widget_Date]) = M.[MonthID]
WHERE (A.[Operator_Name] LIKE '%'+ @OName +'%')
AND A.[PlantID] = '00000001'
AND (
(A.Widget_Date >= @Start_Date AND @End_Date IS NULL)
OR (A.Widget_Datet <= @End_Date AND @Start_Date IS NULL)
OR (A.Widget_Date >= @Start_Date AND A.Widget_Date <= @End_Date)
OR (@Start_Date IS NULL AND @End_Date IS NULL)
GROUP BY M.[MonthName], M.MonthID
ORDER BY M.[MonthID]
下面是这个查询的执行计划。
::UPDATE1:: 我刚刚将月份的名称插入到该表中。我无法更改远程表。
CREATE TABLE [dbo].[Months](
[MonthID] [smallint] IDENTITY(1,1) NOT NULL,
[MonthName] [varchar](25) NOT NULL,
CONSTRAINT [PK_Months] PRIMARY KEY CLUSTERED ([MonthID] ASC)
)
GO
INSERT INTO [dbo].[Months]
([MonthName])
VALUES
(<MonthName, varchar(25),>)
GO
“widget”表有超过 250 个字段,这将花费我太多时间来匿名化。
你的代码说你正在做一个
LEFT OUTER JOIN
,但你真的吗?您的第一个WHERE
子句(以及后面的每个子句)过滤要包含在外表中的行:无论您是否有意,这都会将您
LEFT OUTER JOIN
变成一个。INNER JOIN
也许您打算将这些过滤器移到ON
子句中。当然,我可能会从 中删除 non-sargeable
MONTH()
函数JOIN
,因为这将强制对远程表进行完整扫描,并以这种方式编写它——同时消除与本地月表的连接:只需忽略输出中的
m
列(如果不将其包含在输出中就无法按它排序,按名称排序也没有意义)。另一个建议:不要
'single quotes'
用作别名定界符。这种形式已被弃用,它还使列别名看起来像字符串文字。改用[square brackets]
。