具有以下2个表:
表 MainProcessed :
Id Value
---------
1 123
2 234
3 112
表 MainAdditionalInfo :
Id MainProcessedId Name Value
--------------------------------------
1 1 'PX' 'px_value'
2 1 'PY' 'py_value'
我需要从表MainProcessedId
中选择所有在表MainAdditionalInfo
中具有一些附加信息的数据(至少一个记录),并且它没有名称为PX或如果有,则此值应为null或为空。
这是我尝试过的方法,但是由于这些表具有大量数据(超过1亿条记录,因此查询运行了很多时间):
select mp.*
from MainProcessed mp (nolock)
left join MainAdditionalInfo mai1 (nolock) on mp.Id = mai1.MainProcessedId
left join MainAdditionalInfo mai2 (nolock) on mp.Id = mai2.MainProcessedId
where
(mai1.Value is null or mai1.Value = '')
and (mai1.Name = 'PX' or mai1.Name = null)
and mai2.name = 'PY'
请注意,名称为PX的值可能不存在或可以为空值或空值,但名称为PY的值始终存在。你能建议我改善吗?
此外,我无权查看执行计划或创建新对象(索引)。
答案 0 :(得分:3)
您可以尝试用exists
和not exists
来短语查询:
select p.*
from MainProcessed p
where
exists (
select 1
from MainAdditionalInfo a
where a.MainProcessedId = p.id)
and not exists (
select 1
from MainAdditionalInfo a
where
a.MainProcessedId = p.id
and a.Name = 'PX'
and a.Value <> '' -- null values won't pass that test
)
要获得此查询的性能,您需要在MainAdditionalInfo(MainProcessedId , Name, Value)
上建立索引。
答案 1 :(得分:0)
select mp.*
from MainProcessed mp
left join MainAdditionalInfo mai1 on mp.Id = mai1.MainProcessedId and mai2.name ='PX'
where Id in(
select distinct MainProcessedId
from MainAdditionalInfo mai2
inner join MainProcessed on Id = mai2.MainProcessedId and mai2.name ='PY'
)
and (mai1.Value is null or mai1.Value = '')
答案 2 :(得分:0)
这个评论太长了,但是我在扩展第二个评论。这也不能回答问题(问题中没有足够的细节来回答),但是无论如何它可能会帮助查询计划程序。
首先,您在WHERE
中有2个子句,就像(mai1.Value is null or mai1.Value = '')
我假定,这是因为如果Value
可能是NULL
{1}}失败。如果是这样,请勿在您的JOIN
中处理它,而将其放在WHERE
中。
您也有ON
,但是您对and mai2.name = 'PY'
执行了LEFT JOIN
。这意味着MainAdditionalInfo mai2
现在是隐式JOIN
。因此,我个人将您的查询写为:
INNER JOIN
我还删除了SELECT {List columns, do not use *}
FROM MainProcessed mp
JOIN MainAdditionalInfo mai2 ON mp.Id = mai2.MainProcessedId
LEFT JOIN MainAdditionalInfo mai1 ON mp.Id = mai1.MainProcessedId
AND mai1.Value = ''
AND mai1.Name = 'PX'
WHERE mai2.[name] = 'PY';
提示,因为我怀疑它们弊大于利。 Bad habits : Putting NOLOCK everywhere
答案 3 :(得分:0)
首先,应确保在MainAdditionalInfo
到MainProcessed.ID
上具有FK,索引在MainAdditionalInfo.MainProcessedId
上。另外,您应该在MainAdditionalInfo
和name
列的value
上有一个索引。
如果您不需要join
中的数据,请不要使用MainAdditionalInfo
,请使用exists
,例如:
SELECT mp.*
FROM MainProcessed mp (nolock)
WHERE NOT EXISTS (SELECT 1 FROM MainAdditionalInfo mai1
WHERE mai1.Value > ''
AND mai1.Name = 'PX'
AND mp.Id = mai1.MainProcessedId)
AND EXISTS (SELECT 1 FROM MainAdditionalInfo mai2
WHERE mai2.name = 'PY'
AND mp.Id = mai2.MainProcessedId)