Получить подробные строки группы на основе общего итога - PullRequest
2 голосов
/ 08 ноября 2011

У меня есть таблица, которая выглядит следующим образом:

+------+------+------------------+
| 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 |
+------+------+------------------+

итого, общая сумма всех предметов за день: 16 мая 2011 равна: 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 )

Это не домашняя работа, это реl контекст, в котором я оступился и мне нужно достичь результата одним запросом ...

Запрос должен выполняться без изменений или с небольшими изменениями в MySQL, SQL Server, PostgreSQL.

Ответы [ 2 ]

4 голосов
/ 09 ноября 2011

Вы можете сделать это с помощью одного запроса:

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).В противном случае вы можете попытаться перевести это в коррелированные объединения таблиц и т. Д., Но это будет не красиво, если это возможно (хранимая процедура или повторная сборка на более высоком уровне)язык может быть вашим единственным вариантом).

0 голосов
/ 08 ноября 2011

Я не знаю, как это можно сделать с помощью одного запроса;вам, вероятно, придется создать хранимую процедуру.Шаги процедуры будут выглядеть примерно так:

  1. Рассчитайте общую сумму за этот день, используя SUM
  2. Получите отдельные записи за этот день, упорядоченные по val DESC
  3. Держите промежуточный итог, пока вы просматриваете отдельные записи;до тех пор, пока промежуточный итог <0.8 * grandtotal, добавьте текущую запись в свой список </li>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...