DB - Oracle
create table customer_exercise(
customer_id number,
exercise_id number,
cnt number,
exercise_date date)
数据
1000 10 3 14-AUG-17
1001 20 6 14-AUG-17
1000 20 2 14-AUG-17
当in子句中的条件不存在记录时,是否可以获得默认行?
select customer_id, exercise_id, sum(cnt)
from customer_exercise
where customer_id in (1000, 1001, 1003)
and exercise_id in (10, 20)
group by customer_id, exercise_id
order by sum(cnt)
以上查询的结果 -
1000 20 2
1000 10 3
1001 20 6
由于in子句中的customer-id可能没有某些exercise-id的记录,是否可以使用SQL获得如下所示的结果,其中sum为0?对于例如1001没有exercise-id = 10的记录,因此sum将为0。
1001 10 0
1003 10 0
1003 20 0
1000 20 2
1000 10 3
1001 20 6
答案 0 :(得分:2)
您可以使用:
WITH cte AS (
SELECT *
FROM (SELECT 1000 AS customer_id FROM DUAL UNION
SELECT 1001 FROM DUAL UNION
SELECT 1003 FROM DUAL) s
CROSS JOIN (SELECT 10 AS exercise_id FROM DUAL UNION
SELECT 20 FROM DUAL) s2
)
SELECT c.customer_id , c.exercise_id, COALESCE(sum(ce.cnt),0) AS s
FROM cte c
LEFT JOIN customer_exercise ce
ON c.customer_id = ce.customer_id
AND c.exercise_id = ce.exercise_id
GROUP BY c.customer_id, c.exercise_id
ORDER BY s;
<强> DB Fiddle Demo 强>
当然,您有多种方法可以在cte:
中生成CROSS JOIN
答案 1 :(得分:1)
您可以将in
子句条件转换为集合(例如built-in collection type, handy for this sort of thing),将它们扩展为CTE中的关系数据,然后将它们交叉连接;并且左连接到真实表以查看匹配的内容:
with customer_cte (customer_id) as (
select * from table(sys.odcinumberlist(1000, 1001, 1003))
),
exercise_cte (exercise_id) as (
select * from table(sys.odcinumberlist(10, 20))
)
select c.customer_id, e.exercise_id, coalesce(sum(ce.cnt), 0) as total_cnt
from customer_cte c
cross join exercise_cte e
left join customer_exercise ce
on ce.customer_id = c.customer_id
and ce.exercise_id = e.exercise_id
group by c.customer_id, e.exercise_id
order by coalesce(sum(cnt), 0), customer_id, exercise_id
/
CUSTOMER_ID EXERCISE_ID TOTAL_CNT
----------- ----------- ----------
1001 10 0
1003 10 0
1003 20 0
1000 20 2
1000 10 3
1001 20 6
6 rows selected.
如果您已经拥有单独的customer
和exercise
表,并且它们至少包含您要查找的所有ID,那么您可以直接使用这些表,并过滤它们而不是您的映射表:
select c.customer_id, e.exercise_id, coalesce(sum(ce.cnt), 0) as total_cnt
from customer c
cross join exercise e
left join customer_exercise ce
on ce.customer_id = c.customer_id
and ce.exercise_id = e.exercise_id
where c.customer_id in (1000, 1001, 1003)
and e.exercise_id in (10, 20)
group by c.customer_id, e.exercise_id
order by coalesce(sum(cnt), 0), customer_id, exercise_id
您不会以这种方式获取customer
和exercise
表中不存在的任何ID的默认行,但这可能不是问题。