Sql server 等效查询、不同结果和执行时间

Sql server 等效查询、不同结果和执行时间,sql-server,tsql,join,Sql Server,Tsql,Join,编辑:查询链接到的计划: 因此,我在一个MSSQL系统上工作,我正在重写一些查询。我决定主要通过从WHERE子句中移动谓词,并将它们填充到JOIN子句中来使用谓词。当我这样做的时候,它返回的行数是原来的两倍,执行时间从几秒钟变为几分钟 我想知道发生了什么,因为我认为查询分析器通常会将谓词填充到JOIN子句中,因为这些行最终会被丢弃 如果有人能帮我解释为什么这些查询不相等,我将不胜感激,因为我的数据库不够强大,不知道该去哪里找 好的查询: FROM [CONNECT_PROD].[dbo].[

编辑:查询链接到的计划:

因此,我在一个MSSQL系统上工作,我正在重写一些查询。我决定主要通过从WHERE子句中移动谓词,并将它们填充到JOIN子句中来使用谓词。当我这样做的时候,它返回的行数是原来的两倍,执行时间从几秒钟变为几分钟

我想知道发生了什么,因为我认为查询分析器通常会将谓词填充到JOIN子句中,因为这些行最终会被丢弃

如果有人能帮我解释为什么这些查询不相等,我将不胜感激,因为我的数据库不够强大,不知道该去哪里找

好的查询:

FROM [CONNECT_PROD].[dbo].[CRM_C005] c005 
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_FI] fi ON c005.ID_FI = fi.ID
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_CPPE] kp ON c005.ID_PE = kp.ID_PE AND  fi.id = kp.id_fi
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] vko ON c005.F7010 = vko.code 
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_VF] vf on vf.id_fi = fi.id and vf.VerkOrg = vko.code
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] land ON fi.land = land.code 
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] title ON kp.Titel = title.code and title.loskz = 0 and title.KatSperre = 0 and title.sprachenr = 0 and title.katnr = 23
WHERE kp.loskz = 0
and vko.loskz = 0
and vko.KatSperre = 0
and vko.sprachenr = 0
and vko.katnr = 274
and vko.ExtKey = '0014'
and land.loskz = 0
and land.KatSperre = 0
and land.sprachenr = 1000
and land.katnr = 2
and fi.loskz = 0
and fi.F7029 = 0
and vf.loskz = 0
and vf.F7023 = 0
and vf.F7152 = 0
and c005.del = 0
and kp.f7017 = 0
FROM [CONNECT_PROD].[dbo].[CRM_C005] c005 
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_FI] fi ON c005.ID_FI = fi.ID AND fi.loskz = 0 AND fi.F7029 = 0
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_CPPE] kp ON c005.ID_PE = kp.ID_PE AND fi.id = kp.id_fi AND kp.loskz = 0 AND kp.f7017 = 0
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] vko ON c005.F7010 = vko.code AND vko.loskz = 0 AND vko.KatSperre = 0 AND vko.sprachenr = 0 AND vko.katnr = 274 and vko.ExtKey = '0014'
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_VF] vf on vf.id_fi = fi.id and vf.VerkOrg = vko.code AND vf.loskz = 0 AND vf.F7023 = 0 AND vf.F7152 = 0
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] land ON fi.land = land.code AND land.loskz = 0 AND land.KatSperre = 0 AND land.sprachenr = 1000 AND land.katnr = 2
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] title ON kp.Titel = title.code and title.loskz = 0 and title.KatSperre = 0 and title.sprachenr = 0 and title.katnr = 23
WHERE c005.del = 0
错误查询:

FROM [CONNECT_PROD].[dbo].[CRM_C005] c005 
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_FI] fi ON c005.ID_FI = fi.ID
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_CPPE] kp ON c005.ID_PE = kp.ID_PE AND  fi.id = kp.id_fi
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] vko ON c005.F7010 = vko.code 
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_VF] vf on vf.id_fi = fi.id and vf.VerkOrg = vko.code
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] land ON fi.land = land.code 
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] title ON kp.Titel = title.code and title.loskz = 0 and title.KatSperre = 0 and title.sprachenr = 0 and title.katnr = 23
WHERE kp.loskz = 0
and vko.loskz = 0
and vko.KatSperre = 0
and vko.sprachenr = 0
and vko.katnr = 274
and vko.ExtKey = '0014'
and land.loskz = 0
and land.KatSperre = 0
and land.sprachenr = 1000
and land.katnr = 2
and fi.loskz = 0
and fi.F7029 = 0
and vf.loskz = 0
and vf.F7023 = 0
and vf.F7152 = 0
and c005.del = 0
and kp.f7017 = 0
FROM [CONNECT_PROD].[dbo].[CRM_C005] c005 
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_FI] fi ON c005.ID_FI = fi.ID AND fi.loskz = 0 AND fi.F7029 = 0
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_CPPE] kp ON c005.ID_PE = kp.ID_PE AND fi.id = kp.id_fi AND kp.loskz = 0 AND kp.f7017 = 0
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] vko ON c005.F7010 = vko.code AND vko.loskz = 0 AND vko.KatSperre = 0 AND vko.sprachenr = 0 AND vko.katnr = 274 and vko.ExtKey = '0014'
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_VF] vf on vf.id_fi = fi.id and vf.VerkOrg = vko.code AND vf.loskz = 0 AND vf.F7023 = 0 AND vf.F7152 = 0
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] land ON fi.land = land.code AND land.loskz = 0 AND land.KatSperre = 0 AND land.sprachenr = 1000 AND land.katnr = 2
LEFT JOIN [CONNECT_PROD].[dbo].[CRM_KA] title ON kp.Titel = title.code and title.loskz = 0 and title.KatSperre = 0 and title.sprachenr = 0 and title.katnr = 23
WHERE c005.del = 0

假设这个例子:我有一张100000个电话的表格。电话有几种类型:入站电话和出站电话。当我写一个查询时

SELECT * 
FROM calls c
LEFT JOIN calltypes ct
ON c.calltypeID = ct.calltypeID
WHERE c.calltypeID = 1 --Assume this is inbound
此查询将仅返回my calls表中的入站呼叫

现在,如果我写:

SELECT * 
    FROM calls c
    LEFT JOIN calltypes ct
    ON c.calltypeID = ct.calltypeID
    AND c.calltypeID = 1 

我将返回100000行。左联接找不到合适的联接条件,因此它为ct表的值返回空值。这就是为什么在连接条件中使用where子句时,查询可能会返回更多行的一个示例。

假设这个示例:我有一个包含100000个电话的表。电话有几种类型:入站电话和出站电话。当我写一个查询时

SELECT * 
FROM calls c
LEFT JOIN calltypes ct
ON c.calltypeID = ct.calltypeID
WHERE c.calltypeID = 1 --Assume this is inbound
此查询将仅返回my calls表中的入站呼叫

现在,如果我写:

SELECT * 
    FROM calls c
    LEFT JOIN calltypes ct
    ON c.calltypeID = ct.calltypeID
    AND c.calltypeID = 1 

我将返回100000行。左联接找不到合适的联接条件,因此它为ct表的值返回空值。这就是为什么在连接条件中使用where子句时,查询可能会返回更多行的一个示例。

通过引用连接的外侧,将其转换为常规连接
你不妨这样做

FROM [CONNECT_PROD].[dbo].[CRM_C005] c005 
JOIN [CONNECT_PROD].[dbo].[CRM_FI] fi 
       ON fi.ID    = c005.ID_FI 
      and            c005.del = 0
      and fi.loskz = 0
      and fi.F7029 = 0
JOIN [CONNECT_PROD].[dbo].[CRM_CPPE] kp 
       ON kp.ID_PE = c005.ID_PE  
      AND kp.id_fi = c005.ID_FI 
      and kp.loskz = 0 
      and kp.f7017 = 0
JOIN [CONNECT_PROD].[dbo].[CRM_KA] vko 
       ON vko.code      = c005.F7010     
      and vko.loskz     = 0
      and vko.KatSperre = 0
      and vko.sprachenr = 0
      and vko.katnr     = 274
      and vko.ExtKey    = '0014'
JOIN [CONNECT_PROD].[dbo].[CRM_VF] vf 
       on vf.id_fi   = c005.ID_FI 
      and vf.VerkOrg = vko.code 
      and vf.loskz   = 0
      and vf.F7023   = 0
      and vf.F7152   = 0
JOIN [CONNECT_PROD].[dbo].[CRM_KA] land 
       ON land.code      = fi.land  
      and land.loskz     = 0
      and land.KatSperre = 0
      and land.sprachenr = 1000
      and land.katnr     = 2
JOIN [CONNECT_PROD].[dbo].[CRM_KA] title 
       ON title.code      = kp.Titel 
      and title.loskz     = 0 
      and title.KatSperre = 0 
      and title.sprachenr = 0 
      and title.katnr     = 23

通过引用中连接的外侧,将其转换为常规连接
你不妨这样做

FROM [CONNECT_PROD].[dbo].[CRM_C005] c005 
JOIN [CONNECT_PROD].[dbo].[CRM_FI] fi 
       ON fi.ID    = c005.ID_FI 
      and            c005.del = 0
      and fi.loskz = 0
      and fi.F7029 = 0
JOIN [CONNECT_PROD].[dbo].[CRM_CPPE] kp 
       ON kp.ID_PE = c005.ID_PE  
      AND kp.id_fi = c005.ID_FI 
      and kp.loskz = 0 
      and kp.f7017 = 0
JOIN [CONNECT_PROD].[dbo].[CRM_KA] vko 
       ON vko.code      = c005.F7010     
      and vko.loskz     = 0
      and vko.KatSperre = 0
      and vko.sprachenr = 0
      and vko.katnr     = 274
      and vko.ExtKey    = '0014'
JOIN [CONNECT_PROD].[dbo].[CRM_VF] vf 
       on vf.id_fi   = c005.ID_FI 
      and vf.VerkOrg = vko.code 
      and vf.loskz   = 0
      and vf.F7023   = 0
      and vf.F7152   = 0
JOIN [CONNECT_PROD].[dbo].[CRM_KA] land 
       ON land.code      = fi.land  
      and land.loskz     = 0
      and land.KatSperre = 0
      and land.sprachenr = 1000
      and land.katnr     = 2
JOIN [CONNECT_PROD].[dbo].[CRM_KA] title 
       ON title.code      = kp.Titel 
      and title.loskz     = 0 
      and title.KatSperre = 0 
      and title.sprachenr = 0 
      and title.katnr     = 23

请提供执行计划这些查询不同,因为如果是左外部联接,条件将仅限制从外部联接表中获取的行,并且仍然从CRM_C005中带出行,但在原始查询中,它将完全省略行——因此在where子句中有任何与外部联接相关的内容都会将其转换为内部联接。@dfundako是否有首选上载点?@dfundako Done,已添加计划。请提供执行计划查询不相同,因为如果是左外部联接,条件将仅限制从外部联接表中获取的行,并且仍然从CRM_C005中带出行,但在原始查询中,它将完全省略行——因此,在where子句中包含任何与外部联接相关的内容都会将其转换为内部联接。@dfundako是否有首选上载点?@dfundako完成,计划已添加。天哪,我是如何在不知道区别的情况下走到这一步的!我总是把我的“c.calltypeID”放在WHERE子句中,所以我想我从来没有学过。但是,我可以看到这些额外的行将如何通过使我的结果集膨胀的序列。是的,在原始查询中,您正在将左连接转换为内部连接。。它与您编写的查询不同。如果你一直都在这样做,那么很可能你有很多查询返回错误的结果。天哪,我怎么能在不知道差异的情况下走到这一步!我总是把我的“c.calltypeID”放在WHERE子句中,所以我想我从来没有学过。但是,我可以看到这些额外的行将如何通过使我的结果集膨胀的序列。是的,在原始查询中,您正在将左连接转换为内部连接。。它与您编写的查询不同。如果您一直在这样做,那么可能会有许多查询返回错误的结果。