Кумулятивный SQL % Всего

Мой набор данных выглядит так:

COLA  | COLB
Name1 | 218
Name2 | 157
Name3 | 134
Name4 | 121

Мне нужен этот вывод:

COLA  | COLB| COLC
Name1 | 218 | 0.34
Name2 | 157 | 0.60
Name3 | 134 | 0.71
Name4 | 121 | 1

Мой SQL выглядит так:

SELECT COLA, COLB, COLB/SUM(COLB) FROM #MyTempTable

Две проблемы с этим SQL. Во-первых, COLC всегда равен 0, и я этого не понимаю. Во-вторых, даже если это привело к %, это не кумулятивный %.

Я видел несколько похожих тем на StackOverflow, но мне не удалось заставить ответы из этих тем работать в моем конкретном сценарии.

Спасибо заранее за любые предложения!


person s15199d    schedule 28.08.2012    source источник
comment
вам нужен столбец, чтобы упорядочить строки. как узнать, какая строка будет первой в последовательности?   -  person Beth    schedule 28.08.2012
comment
Убедитесь, что когда вы публикуете вопрос SQL на SO, вы указываете, какую СУБД вы используете. (MySQL? MSSQL? Oracle?)   -  person Sam DeHaan    schedule 28.08.2012
comment
Означает ли обозначение #MyTempTable MS SQL Server? Мы не должны гадать, однако.   -  person Jonathan Leffler    schedule 28.08.2012
comment
SQL 2008 - извиняюсь за то, что не разъяснил это раньше   -  person s15199d    schedule 28.08.2012


Ответы (3)


Я думаю, вы ищете что-то вроде этого, хотя ваши примерные расчеты могут немного отличаться:

SELECT
    COLA,
    COLB,
    ROUND(
        -- Divide the running total...
        (SELECT CAST(SUM(COLB) AS FLOAT) FROM #MyTempTable WHERE COLA <= a.COLA) /
        -- ...by the full total
        (SELECT CAST(SUM(COLB) AS FLOAT) FROM #MyTempTable),
        2
    ) AS COLC
FROM #MyTempTable AS a
ORDER BY COLA

РЕДАКТИРОВАТЬ: я добавил округление.

Это дает нам следующий результат:

COLA    COLB    COLC
Name1   218     0.35
Name2   157     0.6
Name3   134     0.81
Name4   121     1

Причина, по которой ваши результаты равны 0 (или 1), заключается в том, что вы делите целые числа на целые числа, что дает вам целое число (см. приоритет типа данных).

ОБНОВИТЬ:

Я должен добавить, что для запуска всего (WHERE COLA <= a.COLA). В зависимости от вашей версии SQL Server вы можете сравнить это с другими параметрами, если производительность становится заботой.

person Tim Lehner    schedule 28.08.2012
comment
Тим огромное спасибо. Мне нужно иметь возможность ЗАКАЗАТЬ ПО COLB DESC. Я пробовал это... SELECT TOP(10) COLA, COLB, ROUND( -- Разделить промежуточную сумму... (SELECT CAST(SUM(COLB) AS FLOAT) FROM #MyTempTable WHERE COLB ‹= a.COLB) / -- ...полной суммой (SELECT CAST(SUM(COLB) AS FLOAT) FROM #MyTempTable), 2 ) AS COLC FROM #MyTempTable AS A ORDER BY COLB DESC - person s15199d; 28.08.2012
comment
Ничего... Я понял... SELECT TOP(10) COLA, COLB, ROUND( -- Разделить промежуточную сумму... (SELECT CAST(SUM(COLB) AS FLOAT) FROM #MyTempTable WHERE COLB ›= a. COLB) / -- ...полной суммой (SELECT CAST(SUM(COLB) AS FLOAT) FROM #MyTempTable), 2 ) AS COLC FROM #MyTempTable AS A ORDER BY COLB DESC - person s15199d; 28.08.2012

Если вы не используете функции OLAP, вам придется выполнить странное самосоединение таблицы:

SELECT a.ColA, a.ColB, SUM(b.ColB) AS ColX
  FROM #MyTempTable AS a
  JOIN #MyTempTable AS b
    ON a.ColA <= b.ColA
 GROUP BY a.ColA, a.ColB

Это дает вам необработанную кумулятивную СУММУ. Вы определенно можете использовать это как подзапрос для получения ответа, отметив, что для получения процента вам нужно разделить совокупную сумму на общую сумму:

SELECT ColA, ColB, ColX / (SELECT SUM(ColB) FROM MyTempTable) AS ColC
  FROM (SELECT a.ColA, a.ColB, SUM(b.ColB) AS ColX
          FROM #MyTempTable AS a
          JOIN #MyTempTable AS b
            ON a.ColA <= b.ColA
         GROUP BY a.ColA, a.ColB
       ) AS X
 ORDER BY ColA

Вы можете написать просто:

SELECT a.ColA, a.ColB, SUM(b.ColB) / (SELECT SUM(ColB) FROM MyTempTable) AS ColC
  FROM #MyTempTable AS a
  JOIN #MyTempTable AS b
    ON a.ColA <= b.ColA
 GROUP BY a.ColA, a.ColB
 ORDER BY a.ColA

Умножьте выражение ColC на 100, чтобы получить процент вместо дроби.

Протестировано на IBM Informix 11.70.FC2 в Mac OS X 10.7.3, оба запроса с делением работают, давая один и тот же ответ (и я отмечаю, что я получаю 0,81 вместо 0,71, как требуется в вопросе):

Name1    218    0.34603174603174603174603174603175
Name2    157    0.5952380952380952380952380952381
Name3    134    0.80793650793650793650793650793651
Name4    121    1.0 

Возможно, вам придется использовать CAST, чтобы гарантировать, что деление выполняется с использованием арифметики с плавающей запятой вместо целочисленной — как вы можете видеть, в этом не было необходимости с Informix (SUM в любом случае является десятичным числом с плавающей запятой, на случай, если в таблице есть миллиарды). строк в нем, а не только 4 из них). Я мог бы улучшить презентацию, используя ROUND(xxxx, 2), чтобы получить всего 2 знака после запятой; приведение к DECIMAL(6,2) даст тот же результат, но ответственность за представление должен нести клиент, а не СУБД.

person Jonathan Leffler    schedule 28.08.2012

В MS SQL Server это делается (ups, неправильная субагрегация -> неправильный результат):

create table #MyTempTable (cola varchar(10), colb int)

insert into #MyTempTable(cola,colb)
select 'Name1',218
union all
select 'Name2',157
union all
select 'Name3',134
union all
select 'Name4',121

SELECT otab.COLA, otab.COLB,
       cast(otab.COLB as float)/(select SUM(cast(itab.colb as float))
                                 from #MyTempTable itab where itab.cola >= otab.cola) 
  from #MyTempTable otab

drop table #MyTempTable
person Christian    schedule 28.08.2012
comment
Я попытался использовать CAST(COLB/(SELECT SUM(COLB) FROM #MyTempTable) AS DECIMAL(3,2)) AS Pct_Total. Я вижу, что мне нужно было разыграть только дивиденды. Спасибо! - person s15199d; 28.08.2012
comment
Добро пожаловать в Stack Overflow. Использование системы MarkDown для предоставления ответа требует некоторого привыкания. Чтобы код выглядел нормально, сделайте отступ в четыре пробела. Когда вы редактируете, значок {} над полем редактирования будет отступать для выделенного материала на четыре пробела, если в первом (трех) столбце (столбцах) есть символ — он также убирает отступ, если в первом столбце нет ни одного символа. столбец. Доступны кнопки помощи. (Не нужно много времени, чтобы разобраться во всем этом.) - person Jonathan Leffler; 28.08.2012