2015-07-03 2 views
2

Так вот таблица:Расчет с последовательным индикатором

Name Indicator Amount 
Anson  1   3.5 
Anson  2   2.6 
Anson  3   8.4 
Anson  4   3.2 
Anson  6   3.7 
Ben   1   7 
Ben   3   4.7 
Ben   4   3.6 

Как я могу получить сумму суммы, когда индикатор подряд? Это результат, который я хочу:

Name Indicator Amount 
Anson  1,2,3,4 17.7 
Anson  6  3.7 
Ben   1  7 
Ben   3,4  8.3 

Я пробовал это, но он мог сочетать только два последовательных индикатора.

select name_, indicator, amount, sum_amount, 
(CASE WHEN diff = 1 THEN sum_amount ELSE amount END) as final_amount, 
(CASE WHEN diff = 1 THEN convert(varchar(10),prev_ind)+',' +convert(varchar(10),indicator) ELSE convert(varchar(10),indicator) END) as indicator 

FROM (

select name_, indicator, prev_ind, sum(indicator-prev_ind) as diff, amount, 
sum(amount + prev_amount) sum_amount 
from (
    select name_, indicator, lag(indicator,1,0) over (order by name_, indicator) prev_ind, amount, 
    lag(amount,1,0) over (order by name_) prev_amount 
    from tabb 
)g 
where indicator <> 1 
group by name_, indicator, prev_ind, amount 

)u 

Спасибо!

+0

Можете ли вы отправить запрос, который вы пробовали? –

+0

Что бы вы получили, просто не обработав результаты, полученные из сортировки на «Name» и «Indicator»? Это больше похоже на обработку отсортированных результатов, а не на создание некоторого SQL для этого в операции сервера. –

+0

Я пробовал этот запрос, но он мог комбинировать только два последовательных индикатора @RaduGheorghiu – gsql

ответ

0

Sybase поддерживает функцию list. Я думаю, что самый простой способ получить последовательные значения - вычесть row_number() от indicator. Разница является постоянной для последовательных элементов:

select name, list(indicator), sum(amount) 
from (select t.*, 
      (row_number() over (partition by name order by indicator) - indicator 
      ) grp 
     from tabb t 
    ) t 
group by name, grp; 

Честно говоря, я не вижу, что использование list() действительно добавляет к запросу. Вы также можете просто ввести минимальное и максимальное значения:

select name, 
     cast(min(indicator) as varchar(255)) + '-' + cast(max(indicator) as varchar(255)) as range, 
     sum(amount) 
from (select t.*, cast(indicator as varchar(255)) as inds 
      (row_number() over (partition by name order by indicator) - indicator 
      ) grp 
     from tabb t 
    ) t 
group by name, grp; 
+0

это работает для меня, спасибо! – gsql

0

Вы можете решить эту проблему, используя lag()/lead() функции путем группировки столбцов IsConsecutive и столбца имени с последующим подходом;

SELECT P.NAME, 
    LISTAGG(P.INDICATOR,',') WITHIN GROUP(ORDER BY P.INDICATOR) INDICATORS, 
    SUM (P.AMOUNT) TOTAL 
FROM (SELECT Q.AMOUNT, 
      Q.NAME, 
      Q.INDICATOR, 
      CASE WHEN Q.INDICATOR +1 = Q.AFTER OR Q.INDICATOR-1 = Q.BEFORE THEN 'IsConsecutive' ELSE TO_CHAR(Q.INDICATOR) END GRP 
     FROM (SELECT T.AMOUNT, 
        T.NAME, 
        T.INDICATOR, 
        LAG (T.INDICATOR) OVER (PARTITION BY T.NAME ORDER BY T.INDICATOR) BEFORE, 
        LEAD (T.INDICATOR) OVER (PARTITION BY T.NAME ORDER BY T.INDICATOR) AFTER 
       FROM YOUR_TABLE T 
      )Q 
      )P 
GROUP BY P.GRP, P.NAME 
ORDER BY P.NAME 

Я написал этот оператор SQL для базы данных Oracle. Но вы можете легко преобразовать его, если хотите. Это дает желаемый результат:

Name  Indicators Total 
Anson 1,2,3,4  17.7 
Anson 6   3.7 
Ben  1   7 
Ben  3,4   8.3 
+0

Это работает только в том случае, если имя никогда не имеет одного и того же индикатора дважды. Если вы положите, например. («Anson», 2, 3.5) в конце таблицы вы не получите ожидаемого результата. –

+0

Что должно быть, когда имя имеет один и тот же индикатор дважды или более? –

+0

Попробуйте, и вы увидите, что я имею в виду. Ваш код в порядке. Я просто указываю, что набор 'name, indicator' должен быть последовательным –