SQL列出最小和最小的孩子

时间:2014-07-29 15:16:23

标签: sql

有没有更好的方法来列出孩子的年龄(一个新的功能栏)并输出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)

它似乎有效,但我不确定这是否是正确的方法还是有更好的方法呢?

2 个答案:

答案 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)

故事很长:

您必须进行测试以验证,但使用索引,您的解决方案可能是最干净,最有效的。