我使用SQLite并有一个包含名称列表的表,其中一些是同一家族的成员。
'-----------------------------------'
| Id | Last Name | First Name | Age |
------------------------------------|
| 1 | Gordon | James | 5 |
| 2 | Gordon | Mike | 19 |
| 3 | Gordon | Sara | 8 |
| 4 | Gordon | Cludia | 25 |
| 5 | Sagget | Bob | 22 |
| 6 | Saywer | Tom | 9 |
| 7 | Saywer | Jean | 20 |
| 8 | Finn | Hucklberry | 8 |
| 9 | Smith | John | 18 |
| 10 | Smith | Sue | 39 |
'-----------------------------------'
我需要选择所有18岁或以上的人,但只从每个家庭中挑选一名成员。查询应该选择年龄大于或等于18岁的最年轻的人。对于上面的示例,查询应该返回以下人员:
'-----------------------------------'
| Id | Last Name | First Name | Age |
------------------------------------|
| 2 | Gordon | Mike | 19 |
| 5 | Sagget | Bob | 22 |
| 7 | Saywer | Jean | 20 |
| 9 | Smith | John | 18 |
'-----------------------------------'
请注意,Hucklberry Finn不是输出的一部分,因为他不满足18岁或更大的条件,并且他没有兄弟姐妹或亲戚:(。因此,没有“芬兰人”被选中。
实现上述结果的最简单的查询是什么?
以下是我尝试的:
SELECT
id,
last_name,
first_name,
age
FROM
people p
WHERE
age >= 18
and age < (
select min(age) from people where age > 18 and last_name = p.last_name
)
我觉得一定有比我的尝试更正确、更有效的方法。
3条答案
按热度按时间ojsjcaue1#
过滤表中的
age >= 18
并聚集:SQLite从每个组中挑选具有最小年龄的行。
参见demo。
x759pob22#
标准SQL中的典型方法是对行进行排序:
或使用聚合
或使用
WHERE NOT EXISTS <a younger person >= 18 in the same family>
)。在SQLite中,您通常可以得到更简单的操作,如forpas的回答所示,因为它们对裸列的特殊处理,而其他DBMS没有。它有它的限制与关系,虽然我解释如下。因此,这不是一个安全的选择。
更新
在请求评论中,你说如果有两个(或更多)最年轻的18岁以上的家庭成员(想想双胞胎),你只想选择其中一个。我的第一个查询就是这样做的(您必须使用
RANK
或DENSE_RANK
而不是ROW_NUMBER
来获得这两个查询)。我的第二个查询并不像预期的那样工作,因为它会得到两个人。我的第三个查询也选择了这两个查询,但是可以通过将AND younger.age < p.age
替换为AND (younger.age < p.age OR (younger.age = p.age AND younger.id < p.id))
,调整为只选择一个。forpas的答案中显示的SQLite-only查询不能保证工作,因为它可以从不同的行中选择ID和名字。srinivas st的查询作为我的第二个查询,即。也会选择两行。
结论:在可能出现关系的情况下,唯一不应该使用的方法就是裸列方法。根据如何处理关系,选择任何替代方案。
vjrehmav3#
我认为这个查询可以帮助你得到你想要的结果