有条件地计算 SQL 中列的值并考虑 NULL 值
Conditionally COUNT the Value of a Column in SQL and Account for NULL Value
我有一个 SQL 查询,我在其中尝试在 COUNT() 中执行某些条件。我正在使用 PostgreSQL。这是我的原始查询:
SELECT s.schedule_ID as "schedule_ID", schedule_start, schedule_end, spots,
COUNT(CASE a.schedule_ID WHEN s.schedule_ID THEN TRUE ELSE NULL END) as "takenSpots"
FROM schedules s, appointments a
GROUP BY s.schedule_ID
ORDER BY s.schedule_ID;
基本上,只有当它与日程 table 中的 schedule_ID
相匹配时,才会将 schedule_ID
计入约会。问题是此查询不考虑约会 table 中 a.schedule_ID
为空的情况。当它为 null 时,returns 没有 records.I 想要考虑 null 值,如果它为 null,则 return 0.
经过一些研究,我发现像这样的东西一定有效:
SELECT s.schedule_ID as "schedule_ID", schedule_start, schedule_end, spots,
COUNT(CASE a.schedule_ID WHEN s.schedule_ID THEN TRUE WHEN NULL THEN '0' END) as "takenSpots"
FROM schedules s, appointments a
GROUP BY s.schedule_ID
ORDER BY s.schedule_ID;
但是运气不好,即使我检查 NULL 值,仍然没有记录 return。有人可以帮我吗?
感谢您的帮助!
您的 CASE 表达式不起作用的原因是因为您使用的“简写形式”只能测试是否相等,这对于 NULL 值永远不会成立。
所以你需要使用:
CASE WHEN a.schedule_ID = coalesce(s.schedule_ID, a.schedule_ID) then TRUE ELSE NULL END
但是您没有正确加入两个 table。 from a,b
是一个隐式 cross join
在两个 table 之间创建笛卡尔积。
您似乎在寻找一个outer join,然后计算匹配的数量:
SELECT s.schedule_ID as "schedule_ID", schedule_start, schedule_end, spots,
count(a.schedule_id) "takenSpots"
FROM schedules s
LEFT JOIN appointments a on s.schedule_id = a.schedule_id
GROUP BY s.schedule_ID
ORDER BY s.schedule_ID;
外部联接将 return 来自 schedules
table 的所有行,并且只有那些与 appointments
table 匹配的行。对于 schedules
中没有约会的行,a.schedule_id
将为空,而 count()
将忽略这些行。
假设 SELECT 列表中的所有列(a.schedule_id
除外)都来自 schedules
table,有一种稍微更有效的方法:聚合先约会,再做外连接:
SELECT s.schedule_id as "schedule_ID", schedule_start, schedule_end, spots,
coalesce(a.num_appointments,0) as "takenSpots"
FROM schedules s
LEFT JOIN (
select ap.schedule_id, count(*) as num_appointments
from appointments app
group by ap.schedule_id
) a on s.schedule_id = a.schedule_id
ORDER BY s.schedule_id;
我有一个 SQL 查询,我在其中尝试在 COUNT() 中执行某些条件。我正在使用 PostgreSQL。这是我的原始查询:
SELECT s.schedule_ID as "schedule_ID", schedule_start, schedule_end, spots,
COUNT(CASE a.schedule_ID WHEN s.schedule_ID THEN TRUE ELSE NULL END) as "takenSpots"
FROM schedules s, appointments a
GROUP BY s.schedule_ID
ORDER BY s.schedule_ID;
基本上,只有当它与日程 table 中的 schedule_ID
相匹配时,才会将 schedule_ID
计入约会。问题是此查询不考虑约会 table 中 a.schedule_ID
为空的情况。当它为 null 时,returns 没有 records.I 想要考虑 null 值,如果它为 null,则 return 0.
经过一些研究,我发现像这样的东西一定有效:
SELECT s.schedule_ID as "schedule_ID", schedule_start, schedule_end, spots,
COUNT(CASE a.schedule_ID WHEN s.schedule_ID THEN TRUE WHEN NULL THEN '0' END) as "takenSpots"
FROM schedules s, appointments a
GROUP BY s.schedule_ID
ORDER BY s.schedule_ID;
但是运气不好,即使我检查 NULL 值,仍然没有记录 return。有人可以帮我吗?
感谢您的帮助!
您的 CASE 表达式不起作用的原因是因为您使用的“简写形式”只能测试是否相等,这对于 NULL 值永远不会成立。
所以你需要使用:
CASE WHEN a.schedule_ID = coalesce(s.schedule_ID, a.schedule_ID) then TRUE ELSE NULL END
但是您没有正确加入两个 table。 from a,b
是一个隐式 cross join
在两个 table 之间创建笛卡尔积。
您似乎在寻找一个outer join,然后计算匹配的数量:
SELECT s.schedule_ID as "schedule_ID", schedule_start, schedule_end, spots,
count(a.schedule_id) "takenSpots"
FROM schedules s
LEFT JOIN appointments a on s.schedule_id = a.schedule_id
GROUP BY s.schedule_ID
ORDER BY s.schedule_ID;
外部联接将 return 来自 schedules
table 的所有行,并且只有那些与 appointments
table 匹配的行。对于 schedules
中没有约会的行,a.schedule_id
将为空,而 count()
将忽略这些行。
假设 SELECT 列表中的所有列(a.schedule_id
除外)都来自 schedules
table,有一种稍微更有效的方法:聚合先约会,再做外连接:
SELECT s.schedule_id as "schedule_ID", schedule_start, schedule_end, spots,
coalesce(a.num_appointments,0) as "takenSpots"
FROM schedules s
LEFT JOIN (
select ap.schedule_id, count(*) as num_appointments
from appointments app
group by ap.schedule_id
) a on s.schedule_id = a.schedule_id
ORDER BY s.schedule_id;