DB - Oracle。省略了所有约束。
create table customer (cid number(10), cname varchar(50));
create table exercise (eid number(10), ecode varchar(2), score number(2));
-- mapping table
create table customer_exercise (cid number(10), eid number(10), cnt number(10))
Customer table
cid cname
100 e1
200 e2
300 e3
400 e4
Exercise table
eid ecode score
1 c1 5
2 c2 10
3 c3 6
4 c4 3
Customer_Exercise
cid eid count
100 1 2
200 2 5
100 2 3
300 4 10
用于检索总计数的SQL -
SELECT c.cid
,e.eid
,COALESCE(SUM(ce.cnt), 0) AS total_cnt
FROM customer c
CROSS JOIN exercise e
LEFT JOIN customer_exercise ce
ON ce.cid = c.cid
AND ce.eid = e.eid
WHERE c.cid IN (100, 200, 300)
AND e.eid IN (1, 2)
GROUP BY c.cid, e.eid
ORDER by c.cid
结果 -
c.cid e.eid total_cnt
100 1 2
100 2 3
200 1 0
200 2 5
300 1 0
300 2 0
计算每个客户的排名的SQL -
select cid , RANK() OVER (ORDER BY sum(total_score) desc) as rank from
(
SELECT c.cid as cid
,e.eid
,COALESCE(SUM(ce.cnt), 0) AS total_cnt
, COALESCE(SUM(ce.cnt), 0) * e.score as total_score
FROM customer c
CROSS JOIN exercise e
LEFT JOIN customer_exercise ce
ON ce.cid = c.cid
AND ce.eid = e.eid
WHERE c.cid IN (100, 200, 300)
AND e.eid IN (1, 2)
GROUP BY c.cid, e.eid, e.score
)
GROUP BY cid
ORDER BY rank
结果 -
c.cid rank
200 1
100 2
300 3
是否可以使用一个查询而不是上面的两个查询来获取结果集?我希望将上面两个查询的结果合并为一个。预期结果发布在下面。
预期结果 -
c.cid e.eid total_cnt rank
200 1 0 1
200 2 5 1
100 1 2 2
100 2 3 2
300 1 0 3
300 2 0 3
答案 0 :(得分:4)
三个表的连接使用两次 - 一次显示计数,再一次计算排名。第一个版本未聚合,而第二个版本是(并且在聚合后计算分析等级)。这是WITH子句的完美应用:在一个因子子查询(CTE,WITH子句)中连接三个表并使用它两次。
with
j ( cid, eid, score, cnt ) as (
select c.cid, e.eid, e.score, ce.cnt
from customer c cross join exercise e
left outer join customer_exercise ce on c.cid = ce.cid
and e.eid = ce.eid
where c.cid in (100, 200, 300)
and e.eid in (1, 2)
)
select j.cid, j.eid, nvl(j.cnt, 0) as total_count, r.rnk
from j left join ( select cid,
rank() over (order by sum(cnt*score) desc nulls last) as rnk
from j
group by cid
) r
on j.cid = r.cid
order by rnk, eid
;
答案 1 :(得分:0)
您可以使用 SUM(...)OVER(...)计算每位客户的总分,然后按此值排名。
SELECT cid, eid, SUM(cnt) AS total_cnt, DENSE_RANK() OVER (ORDER BY cid, total_score DESC) AS rank
FROM
(
select c.cid, e.eid, e.score, ce.cnt, SUM(ce.cnt * ce.score) OVER (PARTITION BY c.cid) AS total_score
from customer c cross join exercise e
left outer join customer_exercise ce on c.cid = ce.cid
and e.eid = ce.eid
where c.cid in (100, 200, 300)
and e.eid in (1, 2)
) data
GROUP BY cid, eid, total_score
ORDER BY rank, eid
我创建了一个演示here
答案 2 :(得分:0)
我会用两级分析函数来做这件事:
select cid, eid, score, cnt,
dense_rank() over (order by coalece(total_score, 0) desc) as rnk
from (select c.cid, e.eid, e.score, ce.cnt,
sum(e.score) over (partition by c.cid) as total_score
from customer c cross join
exercise e left outer join
customer_exercise ce
on c.cid = ce.cid and e.eid = ce.eid
where c.cid in (100, 200, 300) and e.eid in (1, 2)
) ce;
答案 3 :(得分:-1)
您还可以使用$image = app('App\Helpers\ImageHelper');
专门用于 MS SQL数据库查询
multiple CTE + SUM + DENSE_RANK()