有没有更好的方法来列出孩子的年龄(一个新的功能栏)并输出2个结果,即最小和最大的孩子?
我试过了:
SELECT Name, DOB,
DATEDIFF(YEAR, DOB, GETDATE()) AS Age
FROM Children
WHERE DOB = (SELECT MIN(DOB) FROM Children) OR
DOB = (SELECT MAX(DOB) FROM Children)
它似乎有效,但我不确定这是否是正确的方法还是有更好的方法呢?
答案 0 :(得分:1)
这里有两个子查询,可能需要单独传递每个数据(尽管索引可以帮助)。你也可以这样做:
SELECT Name, DOB, DATEDIFF(YEAR, DOB, GETDATE()) AS Age
FROM Children c JOIN
(SELECT MIN(DOB) as mindob, MAX(DOB) as MAX(dob)
FROM Children
) cm
ON c.DOB = mindob or c.DOB = maxdob;
这样可以在一次通过数据时进行计算。
答案 1 :(得分:1)
我需要查看一些执行计划;但从逻辑上讲,where子句必须在每一行上执行,而不仅仅是一次,而是两次由于or。因此,数据集越大,您的可能性就越长。但是,如果您有DOB索引,我不确定如何改进您的DOB。 所以我们想看看如何可靠地替换OR,或者以某种方式消除那里的行eval。
所以..如果DOB上存在一个索引......你可能会从你已经拥有的东西中获得惊人的表现。
但是,如果不存在索引......需要考虑的其他选项:
使用带有OR的连接我认为连接会增加太多的开销虽然有价值,特别是OR
SELECT Name, DOB, DATEDIFF(YEAR, DOB, GETDATE()) AS Age
FROM Children
INNER JOIN (SELECT min(DOB) y, Max(DOB) z FROM children) a
on a.y=dob
or a.z=dob
如果您的RDBMS支持CTE ...但是union和cte以及join是否设置了where子句和OR的成本?优点是为CTE选择了一次,我们消除了一个或。
with CTE as (SELECT min(DOB) y FROM children UNION Select Max(DOB) z FROM children)
SELECT Name, DOB, DATEDIFF(YEAR, DOB, GETDATE()) AS Age
FROM Children
INNER JOIN CTE
on CTE.y = DOB
或者如果您没有CTE,则子查询可以正常工作。这消除了OR ..但是导致子选择在每一行上发生。
SELECT Name, DOB, DATEDIFF(YEAR, DOB, GETDATE()) AS Age
FROM Children
WHERE DOB in (SELECT min(DOB) y FROM children UNION Select Max(DOB) z FROM children)
或者可能使用exists - 避免可能较慢的OR,但添加了增加时间的子查询。不确定消除OR的好处是否被UNION和子选择所抵消。
SELECT Name, DOB, DATEDIFF(YEAR, DOB, GETDATE()) AS Age
FROM Children
where exists (SELECT 1 FROM
(SELECT min(DOB) y FROM children UNION
SELECT Max(DOB) y FROM children) B
on B.Y = Children.DOB)
故事很长:
您必须进行测试以验证,但使用索引,您的解决方案可能是最干净,最有效的。