SQL子查询和联接

时间:2020-03-25 23:24:15

标签: mysql sql join group-by subquery

捐赠者总金额是人们准备捐赠的血液总量。接受者总金额是该城市所需的总血液量。 必须恰好有两行表示最佳和最差比率。 每行必须包含以下属性:

  1. 城市名称(CITY)
  2. 配给量(捐助方总金额/接收方总金额)

反正我可以将其压缩为一个查询以返回两个值而不是两个单独的查询吗?

SELECT D.City, D.DA/A.AA AS Ratio
FROM
(SELECT City, SUM(Amount) AS DA FROM Donor
GROUP BY City) AS D
JOIN
(SELECT City, SUM(Amount) AS AA FROM Acceptor
GROUP BY City) AS A
ON D.CITY=A.CITY
ORDER BY Ratio ASC
LIMIT 1

SELECT D.City, D.DA/A.AA AS Ratio
FROM
(SELECT City, SUM(Amount) AS DA FROM Donor
GROUP BY City) AS D
JOIN
(SELECT DISTINCT City, SUM(Amount) AS AA FROM Acceptor
GROUP BY City) AS A
ON D.CITY=A.CITY
ORDER BY Ratio DESC
LIMIT 1

3 个答案:

答案 0 :(得分:0)

您应该删除DISTINCT子句,因为在这种情况下不需要使用它们。

假设您使用的是MySQL 8.x(您未提及该版本),则可以使用CTE。您的查询可以重用部分逻辑,并可以采用以下形式:

with 
r as (
  select d.city, d.da/a.aa as ratio
  from (
    select city, sum(amount) as da from donor group by city
  ) d join (
    select city, sum(amount) as aa from acceptor group by city
  ) a on d.city = a.city
)
select city, ratio from r order by ratio limit 1
union 
select city, ratio from r order by ratio desc limit 1

答案 1 :(得分:0)

如果运行的是MySQL 8.0,则可以使用row_number()来执行此操作,这样就无需扫描表(或cte)两次。

select city, ratio
from (
    select 
        d.city, 
        d.da/a.aa ratio, 
        row_number() over(order by d.da/a.aa asc ) rn_asc,
        row_number() over(order by d.da/a.aa desc) rn_desc
    from (select city, sum(amount) as da from donor group by city) d 
    inner join (select city, sum(amount) as aa from acceptor group by city) a 
        on d.city = a.city
) t
where rn_asc = 1 or rn_desc = 1

答案 2 :(得分:0)

您应该删除 DISTINCT 并将两个查询括在 UNION 子句的圆括号中

-- Get the city with worst ratio
(Select a.CITY, d.DonarAmount/a.AcceptorAmount as Ratio
From
(Select CITY, SUM(AMOUNT)as AcceptorAmount
From ACCEPTOR Group by CITY) a
LEFT JOIN
(Select CITY, SUM(AMOUNT) as DonarAmount
From DONOR Group by CITY) d on a.CITY=d.CITY
ORDER BY Ratio ASC
LIMIT 1)

UNION

-- Get the city with the best ratio 
(Select a.CITY, d.DonarAmount/a.AcceptorAmount as Ratio
From
(Select CITY, SUM(AMOUNT)as AcceptorAmount
From ACCEPTOR Group by CITY) a
LEFT JOIN
(Select CITY, SUM(AMOUNT) as DonarAmount
From DONOR Group by CITY) d on a.CITY=d.CITY
ORDER BY Ratio DESC
LIMIT 1);