2017-08-14 28 views
0

DB - 甲骨文默认行的SQL

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 

是否有可能当记录不为条件条款存在获得默认行?上述查询 -

1000 20 2 
1000 10 3 
1001 20 6 

由于客户IDS的条款可能没有某些运动ID的记录,是否有可能使用SQL得到像一个结果

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) 

结果以下总和为0为那些?对于例如1001不具备运动的id = 10的记录,所以总和为0。

1001 10 0 
1003 10 0 
1003 20 0 
1000 20 2 
1000 10 3 
1001 20 6 
+0

使用coalesce(sum(cnt),0) –

+0

您是否有其他表格列出所有客户ID和锻炼ID? –

+0

是的,customer_exercise是一个多对多的映射表。有客户表和锻炼表与客户信息和锻炼信息。 – rayne

回答

1

你可以把你的in子句条件到集合(如built-in collection type, handy for this sort of thing),扩大它们变成关系型数据的热膨胀系数,然后跨加入他们的行列;和左连接到真正的表,看看有什么相匹配:

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. 

如果你已经这样做有单独的customerexercise表,它们至少包含所有你要找的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 

你不会得到默认的行为没有在customerexercise表这种方式存在的任何标识,但是这可能不是一个问题。

+0

非常感谢 – rayne

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

  • 硬编码值
  • 临时表
  • 子查询