我有一些重要的问题要做。我可以用两种方式之一来执行它:
综合而复杂的WHERE
条款:
SELECT *
FROM Talks d
WHERE (d.UserId IN (SELECT SomeGuyUserId FROM Network WHERE MainUserId = @ViewerUserId AND IsX = 0 AND IsY = 0)
AND DATEDIFF(DAY,d.Started,GETDATE()) < 3
AND d.Status <= 100)
OR
(d.UserId IN (SELECT SomeGuyUserId FROM Network WHERE MainUserId = @ViewerUserId AND IsX = 1 AND IsY = 0)
AND DATEDIFF(DAY,d.Started,GETDATE()) < 3
AND d.Status <= 110)
ORDER BY d.UserId;
两个不同的SELECTS
与UNION
:
SELECT *
FROM Talks d
WHERE (d.UserId IN (SELECT SomeGuyUserId FROM Network WHERE MainUserId = @ViewerUserId AND IsX = 0 AND IsY = 0)
AND DATEDIFF(DAY,d.Started,GETDATE()) < 3
AND d.Status <= 100)
UNION
SELECT *
FROM Talks d
(d.UserId IN (SELECT SomeGuyUserId FROM Network WHERE MainUserId = @ViewerUserId AND IsX = 1 AND IsY = 0)
AND DATEDIFF(DAY,d.Started,GETDATE()) < 3
AND d.Status <= 110)
我有三个问题:
ORDER BY
)(如第一个选项中所示)。PS。所有表格都很大(每个表格大于10M),这个查询应该被某些网站广泛使用。
答案 0 :(得分:1)
在许多情况下,SQL Server在优化OR
方面非常糟糕,因此您最好使用UNION
。但唯一可以确定的方法是针对代表性的大型数据库测试两个查询。使用SQL事件探查器来比较度量标准。
另一种方法是重构方法1的WHERE子句;尝试将OR
更深地移动到表达式树中,或者如果可能的话,完全消除它。例如:
SELECT *
FROM Talks d
INNER JOIN Network n ON n.SomeGuyUserId = d.UserId
WHERE n.MainUserId = @ViewerUserId
AND n.IsX IN (0, 1)
AND n.IsY = 0
AND DATEDIFF(DAY, d.Started, GETDATE()) < 3
AND d.Status <= CASE n.IsX WHEN 0 THEN 100 WHEN 1 THEN 110 END
ORDER BY d.UserId;
请注意,此查询可能会导致重复记录,因为我已使用联接替换了IN <subquery>
。如果表MainUserId
中存在SomeGuyUserId
和Network
的重复组合,则会发生这种情况。如果可能,请使用唯一约束来避免这种情况。
答案 1 :(得分:0)
您必须查看两个查询的执行计划才能确定。可能会发生两件不同的事情:
第一个查询会在Talks
上产生一次全表扫描,而。{
第二个查询导致两个全表扫描(一个用于联合的每个部分)。在那种情况下,第一个
查询可能更快。
第一个查询会在Talks
上产生一次全表扫描,而。{
第二个查询导致两个索引范围扫描。在那种情况下,
第二个查询可能更快。
答案 2 :(得分:0)
基本上你的第一个sql查询不是很复杂。与我多年来看到的所有查询相比,它实际上是一个简单的...我只是提取DATEDIFF并继续... ...
SELECT *
FROM Talks d
WHERE DATEDIFF(DAY,d.Started,GETDATE()) < 3
and ( (d.UserId IN (SELECT SomeGuyUserId FROM Network WHERE MainUserId = @ViewerUserId AND IsX = 0 AND IsY = 0) AND d.Status <= 100)
OR
(d.UserId IN (SELECT SomeGuyUserId FROM Network WHERE MainUserId = @ViewerUserId AND IsX = 1 AND IsY = 0) AND d.Status <= 110)
)
ORDER BY d.UserId;