复杂的SQL查询(GROUP BY)

时间:2012-11-11 23:23:47

标签: mysql sql

我需要一些帮助来构建查询。

这就是我需要的:

我有一个名为数据的表格:

   ID| PRODUCT | VALUE |COUNTRY|  DEVICE | SYSTEM 
-----+---------+-------+-------+---------+--------
48   |    p1   |  0.4  |   US  |  dev1   | system1   
47   |    p2   |  0.67 |   IT  |  dev2   | system2   
46   |    p3   |  1.2  |   GB  |  dev3   | system3          
45   |    p1   |  0.9  |   ES  |  dev4   | system4   
44   |    p1   |  0.6  |   ES  |  dev4   | system1 

我需要展示哪些产品的收入最高,哪个国家,设备和系统贡献最多。

**例如:我从表中得到的结果是:

 PRODUCT | TOTAL COST |COUNTRY|  DEVICE | SYSTEM 
  -------+------------+-------+---------+--------
    p1   |     1.9    |   ES  |  dev4   | system1   
    p2   |     0.67   |   IT  |  dev2   | system2   
    p3   |     1.2    |   GB  |  dev3   | system3 

最佳国家是ES,因为ES贡献了0.9 + 0.6 = 1.5> 0.4(美国的贡献)。

顶级设备和顶级系统的逻辑相同。**

我想总收入和产品会是这样的:

SELECT SUM(value) as total_revenue,product FROM data GROUP BY product

但是我如何添加国家/地区,设备和系统?

这在单个查询中是否可行,如果不是最好的方法(表现明智)呢?

非常感谢你的帮助。

修改 我编辑了样本表以便更好地解释。

3 个答案:

答案 0 :(得分:1)

在单独的查询中执行:

SELECT   product,
         SUM(value) AS amount
FROM     data
GROUP BY country    -- change to device, system, etc. as required
ORDER BY amount DESC
LIMIT    1

答案 1 :(得分:1)

你是对的......它不仅仅是一个简单的查询......而是包含在一个结果中的3个查询。

我已将我的样本发布在SQL Fiddle here...

第一个查询 - 最内层。您需要根据每个产品/国家/地区获得所有收入,并根据产品对其进行排序,并根据总收入对其进行排序,以便在每个产品的第一个位置获得最高收入。

下一个查询(我已经实现了使用MySQL @variable的用法)。由于第一个结果订单已经按照产品和收入排名的顺序排列,因此每当产品从“@LastProd”变为什么时,我将等级设置为1 ...这将为产品1创建ES = Rank#1,然后US =产品1的排名#2,然后继续使用其他“产品”。

最后一个最外层的查询重新加入到原始数据表中,但获得了包含相关产品销售的所有设备和系统的列表,但仅限于产品等级为#1的位置。

select
      pqRank.product,
      pqRank.country,
      pqRank.revenue,
      group_concat( distinct d2.device ) as PartDevices,
      group_concat( distinct d2.system ) as PartSystems
   from
      ( select
              pq.product,
              pq.country,
              pq.revenue,
              @RevenueRank := if( @LastProd = pq.product, @RevenueRank +1, 1 ) as ProdRank,
              @LastProd := pq.product
           from
              ( select 
                      d.product,
                      d.country,
                      sum( d.value ) as Revenue
                   from
                      data d
                   group by 
                      d.product,
                      d.country
                   order by
                      d.product,
                      Revenue desc ) pq,
              ( select @RevenueRank := 0,
                       @LastProd := ' ') as sqlvars
      ) pqRank
         JOIN data d2
            on pqRank.product = d2.product
           and pqRank.country = d2.country
   where
      pqRank.ProdRank = 1
   group by
      pqRank.product,
      pqRank.country

答案 2 :(得分:0)

你可以这样做

CREATE TABLE data 
(
id int auto_increment primary key, 
product varchar(20), 
country varchar(4),
device varchar(20),
system varchar(20),
value decimal(5,2)
);

INSERT INTO data (product, country, device, system, value)
VALUES 
('p1', 'US', 'dev1', 'system1', 0.4), 
('p2', 'IT', 'dev2', 'system2', 0.67), 
('p1', 'IT', 'dev1', 'system2', 0.23);

select 'p' as grouping_type, product, sum(value) as sumval
from data
group by product
union all
select 'c' as grouping_type, country, sum(value) as sumval
from data
group by country
union all
select 'd' as grouping_type, device, sum(value) as sumval
from data
group by device
union all
select 's' as grouping_type, system, sum(value) as sumval
from data
group by system
order by grouping_type, sumval

这很难看,我不会用它,但它应该有用。