Sql server 等效查询、不同结果和执行时间
编辑:查询链接到的计划: 因此,我在一个MSSQL系统上工作,我正在重写一些查询。我决定主要通过从WHERE子句中移动谓词,并将它们填充到JOIN子句中来使用谓词。当我这样做的时候,它返回的行数是原来的两倍,执行时间从几秒钟变为几分钟 我想知道发生了什么,因为我认为查询分析器通常会将谓词填充到JOIN子句中,因为这些行最终会被丢弃 如果有人能帮我解释为什么这些查询不相等,我将不胜感激,因为我的数据库不够强大,不知道该去哪里找 好的查询:Sql server 等效查询、不同结果和执行时间,sql-server,tsql,join,Sql Server,Tsql,Join,编辑:查询链接到的计划: 因此,我在一个MSSQL系统上工作,我正在重写一些查询。我决定主要通过从WHERE子句中移动谓词,并将它们填充到JOIN子句中来使用谓词。当我这样做的时候,它返回的行数是原来的两倍,执行时间从几秒钟变为几分钟 我想知道发生了什么,因为我认为查询分析器通常会将谓词填充到JOIN子句中,因为这些行最终会被丢弃 如果有人能帮我解释为什么这些查询不相等,我将不胜感激,因为我的数据库不够强大,不知道该去哪里找 好的查询: FROM [CONNECT_PROD].[dbo].[
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子句中,所以我想我从来没有学过。但是,我可以看到这些额外的行将如何通过使我的结果集膨胀的序列。是的,在原始查询中,您正在将左连接转换为内部连接。。它与您编写的查询不同。如果您一直在这样做,那么可能会有许多查询返回错误的结果。