Sql 使用Group By汇总表中的空值
我有两张桌子:Sql 使用Group By汇总表中的空值,sql,sqlite,group-by,Sql,Sqlite,Group By,我有两张桌子: 人员(身份证、姓名) 运动(个人识别码,运动) 问题是:Sport可能有空值。如果是这样的话,那么如果我按ID分组,运动应该是空的 SELECT p.ID, p.Name, s.Sport FROM Person p INNER JOIN Sports s ON p.ID=s.person_id GROUP BY p.ID 如果不按表分组,则如下所示: p.ID p.Name s.Sport 1 tom soccer 1 tom NULL 2
- 人员(身份证、姓名)
- 运动(个人识别码,运动)
SELECT p.ID, p.Name, s.Sport
FROM Person p
INNER JOIN Sports s ON p.ID=s.person_id
GROUP BY p.ID
如果不按表分组,则如下所示:
p.ID p.Name s.Sport
1 tom soccer
1 tom NULL
2 lisa golf
2 lisa soccer
3 tim golf
3 tim NULL
我现在想要的是:
1 tom NULL
2 lisa golf
3 tim NULL
但我得到的是:
1 tom soccer
2 lisa golf
3 tim golf
我尝试过子选择和ifs,但没有任何效果。提前谢谢 这里有一个查询,可以生成您的预期结果集,尽管@jarlh已经指出,不清楚为什么Lisa应该打高尔夫而不是足球
SELECT
p.ID,
p.Name,
CASE WHEN COUNT(CASE WHEN s.Sport IS NULL THEN 1 END) > 0
THEN NULL ELSE MIN(s.Sport) END AS Sport
FROM Person p
INNER JOIN Sports s
ON p.ID = s.person_id
GROUP BY
p.ID,
p.name;
请注意,我同时按
ID
和name
进行分组,这在许多数据库上都是必需的(虽然可能不是SQLite)。不能使用aggreagtion函数作为MIN()来管理空值
但是你可以试试
SELECT p.ID, p.Name, min(ifnull(s.Sport,''))
FROM Person p
INNER JOIN Sports s ON p.ID=s.person_id
GROUP BY p.ID, p.name
假设您使用的SQLLite版本支持
行号()
,请尝试以下操作,如果您订购s.sport ASC
,则可以将行号设置为1,然后为每个类别选择第一行。如果为空,则应通过此查询定位在每个类别的顶行。您不需要使用分组依据
:
;with cte as (
select p.ID, p.Name, s.Sport,
ROW_NUMBER() OVER (PARTITION BY p.ID ORDER BY s.Sport ASC) AS rn
FROM Person p INNER JOIN Sports s ON p.ID=s.person_id
)
select *
from cte
where rn=1
可以使用相关子查询执行此操作,避免外部查询中的join
:
select p.*,
(select s.sport
from sports s
where s.personId = p.id
order by (s.sport is null) desc, s.sport asc
) as min_sport
from person p;
在某些情况下,这可能是有用的。在运动(personid,sport)
上有一个索引,它可能比组快
,这取决于数据(很多人,每人很少运动)
此外,这与您的查询略有不同,因为它返回所有人,即使是没有运动的人。为什么Lisa应该打高尔夫而不是足球?如果我运行此功能,如果有多人(在我的系统上),Group by函数总是选择第一行。但这并不重要。我只需要tim和tom是select列表中的空用例表达式,就可以进行条件聚合。如果列有空值,请记住count(*)count(column)。@stuckon在这里,为什么不将sport为空的添加到查询中呢?如果我只添加为空,它会删除lisa条目,我需要这个条目。当然,这是假设OP版本的SQLite支持行数
。这是可行的!这是非常有用的表达式计数(Case…)。谢谢。