根据总计检索组的详细信息行

时间:2011-11-08 18:41:41

标签: mysql sql sql-server postgresql grouping

我有一张看起来像这样的表:

+------+------+------------------+
| item | val  |    timestamp     |
+------+------+------------------+
|  1   | 3.66 | 16-05-2011 09:17 | 
|  1   | 2.56 | 16-05-2011 09:47 | 
|  2   | 4.23 | 16-05-2011 09:37 | 
|  3   | 6.89 | 16-05-2011 11:26 | 
|  3   | 1.12 | 16-05-2011 12:11 |
|  3   | 4.56 | 16-05-2011 13:23 |
|  4   | 1.10 | 16-05-2011 14:11 |
|  4   | 9.79 | 16-05-2011 14:23 |
|  5   | 1.58 | 16-05-2011 15:27 |
|  5   | 0.80 | 16-05-2011 15:29 |
|  6   | 3.80 | 16-05-2011 15:29 |
+------+------+------------------+

所以,当天所有项目的总计: 2011年5月16日是: 40.09

现在我想检索此列表中的哪些项目占总数的80%。 让我举个例子:

  • 总计:40.09
  • 总计的80%:32.07

从总金额百分比权重的项目开始,我想要检索构成总计80%的项目的分组列表:

+------+------+
| item | val  |
+------+------+
|  3   | 12.57|
|  4   | 10.89|
|  1   |  6.22|
+------+------+

正如您所看到的,结果集中的元素是按项目代码分组的元素,并从元素中排序,在总计下降百分比中具有更大的权重,直到达到80%阈值。

从第2项开始,项目将从结果集中丢弃,因为它们超过了80%的阈值,因为:

12.57 + 10.89 + 6.22 + 4.23 > 32.07 (80 % of the grand total )

这不是作业,这是一个真实的背景,我被绊倒,我需要通过一个查询来实现结果......

查询应该在MySQL,SQL Server,PostgreSQL上进行未修改或几乎没有更改。

2 个答案:

答案 0 :(得分:4)

可以使用单个查询执行此操作:

WITH Total_Sum(overallTotal) as (SELECT SUM(val) 
                                 FROM dataTable), 

     Summed_Items(id, total) as (SELECT id, SUM(val)
                                 FROM dataTable
                                 GROUP BY id),

     Ordered_Sums(id, total, ord) as (SELECT id, total, 
                                         ROW_NUMBER() OVER(ORDER BY total DESC)
                                      FROM Summed_Items),

     Percent_List(id, itemTotal, ord, overallTotal) as (
                  SELECT id, total, ord, total
                  FROM Ordered_Sums
                  WHERE ord = 1
                  UNION ALL
                  SELECT b.id, b.total, b.ord, b.total + a.overallTotal
                  FROM Percent_List as a
                  JOIN Ordered_Sums as b
                  ON b.ord = a.ord + 1
                  JOIN Total_Sum as c
                  ON (c.overallTotal * .8) > (a.overallTotal + b.total))

SELECT id, itemTotal
FROM Percent_List

将产生以下结果:

id      itemTotal
3       12.57  
4       10.89  
1       6.22  

请注意,这将在mySQL(无CTE)中工作,并且需要更新版本的postgreSQL才能工作(否则不支持OLAP功能)。 SQLServer应该能够按原样运行语句(我认为 - 这是在DB2上编写和测试的)。否则,您可以尝试将其转换为相关的表连接等,但如果它甚至可能(那么<存储过程或重新组装更高级别的语言可能是您唯一的选择。)

答案 1 :(得分:0)

我不知道用单个查询可以做到这一点;你可能需要创建一个存储过程。 proc的步骤是这样的:

  1. 使用SUM
  2. 计算当天的总计
  3. 获取val DESC
  4. 订购当天的个人记录
  5. 循环浏览各个记录时保持运行总计;只要运行总数<&lt; 0.8 * grandtotal,将当前记录添加到您的列表中