Intereting Posts
Продвинутый SQL-запрос Есть ли способ передать набор значений в качестве параметра в Oracle SQL Statement Получение первого дня недели в MySql с использованием Week No java.sql.SQLException: Не найдено подходящего драйвера для jdbc: mysql: // localhost: 3306 / dbname ORA-01219: база данных не открыта: запросы разрешены только для фиксированных таблиц / просмотров Как получить доступ к дублированным именам столбцов с помощью JSTL sql: query? PostgreSQL: как объединить несколько строк? Могу ли я писать SQL, используя распознавание речи? Удаление с использованием нескольких таблиц и повторная таблица в подзапросе Удаление повторяющихся строк в MySQL SQL: возвращает «true», если список записей существует? (My) SQL полное соединение с тремя таблицами Удаление промежуточных пространств и обновление в столбцах в SQL Server Запросы MySQL UNION 2, содержащие ORDER BYs При обновлении записей произошла ошибка. См. Внутреннее исключение для деталей

Групповая строка по сумме определенной колонки, равной удельной стоимости

Это так или иначе, чтобы сгруппировать данные по определенному значению. Например, в таблице есть столбец «Сумма», я хочу сгруппировать строки на каждые 100 единиц без цикла / курсора 🙂

DueAmount = 100

Структура таблицы чеков:

ReceiptNo Amount ------------------ R1 100 R2 100 R3 70 R4 50 R5 200 

Выход: (Группируйте таблицу приема на 100)

 DueNo/GroupKey ReceiptNo Amount -------------------------------------- D1 R1 100 D2 R2 100 D3 R3 70 D3 R4 30 D4 R4 20 D4 R5 80 D5 R5 100 D6 R5 20 

С помощью таблицы-помощника, определяющей границы «Due», наложенных на исходную таблицу с рассчитанной общей суммой, можно вычислить пересечение каждой текущей общей суммы с границами «Due»:

 With Receipt As ( --< Sample source table Select * From (Values ('R1', 100), ('R2', 100), ('R3', 70), ('R4', 50), ('R5', 200) ) V (ReceiptNo, Amount) ), ReceiptWithTotal As ( --< Source table with Running Totals calculated Select *, SUM(Amount) Over (Order By ReceiptNo Rows Unbounded Preceding) - Amount As RunningTotalBefore, SUM(Amount) Over (Order By ReceiptNo Rows Unbounded Preceding) As RunningTotalAfter From Receipt ), Due As ( --< Helper table to define intervals (can be generated dynamically to cover any Total) Select * From (Values ('D1', 0, 100), ('D2', 100, 200), ('D3', 200, 300), ('D4', 300, 400), ('D5', 400, 500), ('D6', 500, 600) ) V (DueNo, AmountLow, AmountHigh) ) Select DueNo, ReceiptNo, IIF(AmountHigh < RunningTotalAfter, AmountHigh, RunningTotalAfter) - IIF(AmountLow > RunningTotalBefore, AmountLow, RunningTotalBefore) As Amount From Due Inner Join ReceiptWithTotal On NOT (RunningTotalAfter <= AmountLow OR RunningTotalBefore >= AmountHigh) 

Обратите внимание: SUM(...) Over (Order By ... Rows Unbounded Preceding) и IIF(...) доступны только на SQL Server 2012+. То же самое можно сделать и на SQL Server 2008 с помощью подзапроса, но гораздо менее эффективным:

 With Receipt As ( --< Sample source table Select * From (Values ('R1', 100), ('R2', 100), ('R3', 70), ('R4', 50), ('R5', 200) ) V (ReceiptNo, Amount) ), ReceiptWithTotal As ( --< Source table with Running Totals calculated Select *, RunningTotalAfter - Amount As RunningTotalBefore From ( Select *, (Select SUM(Amount) From Receipt B Where B.ReceiptNo <= A.ReceiptNo) As RunningTotalAfter From Receipt A ) A ), Due As ( --< Helper table to define intervals (can be generated dynamically to cover any Total) Select * From (Values ('D1', 0, 100), ('D2', 100, 200), ('D3', 200, 300), ('D4', 300, 400), ('D5', 400, 500), ('D6', 500, 600) ) V (DueNo, AmountLow, AmountHigh) ) Select DueNo, ReceiptNo, CASE WHEN AmountHigh < RunningTotalAfter THEN AmountHigh ELSE RunningTotalAfter END - CASE WHEN AmountLow > RunningTotalBefore THEN AmountLow ELSE RunningTotalBefore END As Amount From Due Inner Join ReceiptWithTotal On NOT (RunningTotalAfter <= AmountLow OR RunningTotalBefore >= AmountHigh)