AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 43682
Accepted
RateControl
RateControl
Asked: 2013-06-04 06:46:26 +0800 CST2013-06-04 06:46:26 +0800 CST 2013-06-04 06:46:26 +0800 CST

执行计划与存储过程不匹配

  • 772

下面是一个存储过程,用于计算一个月内制作的小部件数量。如果没有制作任何小部件,则不会存在任何记录。

执行计划显示了INNER JOINM 和 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 个字段,这将花费我太多时间来匿名化。

t-sql sql-server-2012
  • 1 1 个回答
  • 127 Views

1 个回答

  • Voted
  1. Best Answer
    Aaron Bertrand
    2013-06-04T07:12:19+08:002013-06-04T07:12:19+08:00

    你的代码说你正在做一个LEFT OUTER JOIN,但你真的吗?您的第一个WHERE子句(以及后面的每个子句)过滤要包含在外表中的行:

    WHERE     (A.[Operator_Name] LIKE '%'+ @OName +'%')
    

    无论您是否有意,这都会将您LEFT OUTER JOIN变成一个。INNER JOIN也许您打算将这些过滤器移到ON子句中。

    当然,我可能会从 中删除 non-sargeableMONTH()函数JOIN,因为这将强制对远程表进行完整扫描,并以这种方式编写它——同时消除与本地月表的连接:

    DECLARE 
      @OName      VARCHAR(50) = 'John', 
      @Start_Date DATE = NULL,--'20120101', -- use safe date formats 
      @End_Date   DATE = '20121231'; -- use semi-colons
    
    -- deal with NULLs here so the query is simpler:
    
    SELECT @Start_Date = COALESCE(@Start_Date, '20010101'),
           @End_Date   = COALESCE(@End_Date, CURRENT_TIMESTAMP);
    
    ;WITH n(n) AS 
    (
      -- get the # of months you need instead of relying on your Connector table:
      SELECT TOP (DATEDIFF(MONTH, @Start_Date, @End_Date)+1) Number
        FROM master..spt_values
        WHERE [type] = N'P' AND Number >= 0
        ORDER BY Number
    ), m(m) AS
    (
      -- convert those to months:
      SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, @Start_Date), 0))
      FROM n
    )
    SELECT 
      m.m, 
      MonthName = DATENAME(MONTH, m.m),
      [Widget Count] = COUNT(w.Widget_ID)
    FROM m
    LEFT OUTER JOIN [Server].[Database].dbo.Widget AS w -- meaningful alias
    ON 
      w.Widget_Date >= m.m
      AND w.Widget_Date < DATEADD(MONTH, 1, m.m) -- open-ended date range query
      AND w.Operator_Name LIKE '%' + @OName + '%'
    GROUP BY m.m
    ORDER BY m.m;
    

    只需忽略输出中的m列(如果不将其包含在输出中就无法按它排序,按名称排序也没有意义)。

    另一个建议:不要'single quotes'用作别名定界符。这种形式已被弃用,它还使列别名看起来像字符串文字。改用[square brackets]。

    • 7

相关问题

  • 如何判断 SQL Server 数据库是否仍在使用?

  • 为什么 Denali 序列应该比标识列表现更好?

  • 实施 PIVOT 查询

  • SQL Server 不应该支持范围吗?

  • 什么是 SQL Server“德纳利”?什么是新的?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    授予用户对所有表的访问权限

    • 5 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve