如何在sql

时间:2019-07-18 20:27:10

标签: sql

写一个查询,确定每个国家在音乐上花费最多的客户。编写一个查询,返回该国家和最大客户以及他们花费了多少。对于共享最高消费金额的国家/地区,请提供所有使用此金额的客户。

您只需要使用“客户”和“发票”表。

我想选择在每个国家/地区花费最多的顾客,并且有两个顾客在同一国家/地区花费相同的金钱,所以当按组使用时,我只有1个顾客,我应该怎么做?

select c.CustomerId,c.FirstName,c.LastName, c.Country , max(c.Invoices) as TotalSpent 
from
   (select * , sum(i.Total) as 'Invoices'
   from Customer d
   join Invoice i on i.CustomerId = d.CustomerId
   group by i.CustomerId
) c  
group by c.Country 

我得到的表与1位顾客相同,是期望的表

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:0)

您的内部查询几乎是正确的。应该是

select d.*, sum(i.Total) as Invoices
from Customer d
join Invoice i on i.CustomerId = d.CustomerId
group by d.CustomerId

这里可以使用d.*,因为我们可以假设d.CustomerId是表的主键,因此表中的所有列在功能上都依赖于它。例如,如果我们按d.country分组,则不是这种情况,并且select子句(以及d.*等中将禁止d.firstname)。我们只能选择(直接或间接)分组的列以及MINMAXSUM等聚合。

此查询为您提供每个客户以及客户所在国家/地区的总数。

但是,您将获得此结果并按country分组。如果执行此操作,则只能访问country及其集合。例如,选择c.CustomerId是无效的,因为每个国家/地区没有 客户ID。如果您的DBMS允许这样做,则在这方面有缺陷,您会得到某种随机结果。

如果您的DBMS具有窗口功能,则可以即时获取每个国家/地区的最高金额:

select customerid, firstname, lastname, country, invoices
from
(
  select
    c.*,
    sum(i.total) as invoices,
    max(sum(i.total)) over (partition by c.country) as max_sum
  from customer c
  join invoice i on i.customerid = c.customerid
  group by c.customerid
) per_customer
where invoices = max_sum
order by country, customerid;

否则,您将必须使用两次内部查询,一次是获取国家/地区总计,一次是使与这些总计相匹配的客户:

select 
  c.customerid, c.firstname, c.lastname, c.country,
  sum(i.total) as invoices
from customer c
join invoice i on i.customerid = c.customerid
group by c.customerid
having (c.country, invoices) in
(
  select country, max(invoices)
  from
  (
    select
      --c.customerid, <- optional, it may make this query more readable
      c.country,
      sum(i.total) as invoices
    from customer c
    join invoice i on i.customerid = c.customerid
    group by c.customerid
  ) per_customer
);

答案 1 :(得分:0)

考虑通过两个汇总查询加入单位级别:1)首先通过 CustomerId Country 计算总金额,然后2)通过计算最大总金额国家

以下假设您的数据库使用WITH子句(几乎所有主要的商业或开源RDBMS都支持)支持公用表表达式(CTE)。此处的CTE避免了将 sum_agg 作为子查询重复的需求。

with sum_agg AS (
    select i.CustomerId, sub_c.Country, sum(i.Total) as Sum_Amount
    from Customer sub_c
    join Invoice i on i.CustomerId = sub_c.CustomerId
    group by i.CustomerId, sub_c.Country     
)

select c.CustomerId, c.FirstName, c.LastName, c.Country, max_agg.Max_Sum
from Customer c
join sum_agg
   on c.CustomerId = sum_agg.Customer_Id and c.Country = sum_agg.Country 
join 
   (select Country, max(Sum_Amount) as Max_Sum
    from sum_agg
    group by Country
   ) max_agg
   on max_agg.Country = sum_agg.Country and max_agg.Max_Sum = sum_agg.Sum_Amount