2014-12-08 3 views
2

У меня есть таблица, как показано ниже.SQL для вычисления суммы всех возможных комбинаций чисел в столбце

`Col (number) 
1 
2 
4 
8 
` 

Я ищу, чтобы написать SQL, который даст мне выход, как показано ниже, суммируя все различные комбинации значений в столбце в нескольких строках.

`3 (1+2) 
5 (1+4) 
9 (1+8) 
.... 
.... 
7(1+2+4) 
11(1+2+8) 
14(2+4+8) 
15(1+2+4+8)` 
+0

Какую версию Oracle у вас есть? И, если у вас в таблице больше пары десятков строк, результат будет слишком большим для вас, чтобы что-либо сделать. –

+0

Oracle 11g. Таблица будет иметь 5-10 записей –

ответ

1

Oracle 11gR2 поддерживает рекурсивный КТР, так что может быть выражено как:

with nums as (
     select 1 as n union all select 10 union all select 100 union all select 1000 
    ), 
    t(n, vals, cnt) as (
     select n, cast(n as varchar(255)) as vals, 1 as cnt 
     from nums 
     union all 
     select t.n + nums.n, cast(vals || '+' || nums.n as varchar(255)), cnt + 1 
     from t join 
      nums 
      on nums.n > t.n 
    ) 
select * 
from t; 

Там может быть подобный метод с использованием connect by, но я больше знаком с рекурсивной КТР.

+0

[CROSS JOIN не работает в Oracle, но INNER JOIN работает] (http://sqlfiddle.com/#!4/d41d8/38440). Кроме того, если числа не уникальны, этот запрос может не дать полного результата. – Noel

+0

@ EatÅPeach. , , Я признаю, что я не тестировал это на Oracle (я тестировал его на Postgres), но я исправил ответ. Вопрос OP не имеет повторяющихся значений. Если они есть, их легко фиксировать просто перечислением их и использованием перечисления, а не самого значения при добавлении «большего» значения. –

2

Это сделало трюк для меня, используя рекурсивный WITH.

Обратите внимание, что я не получал повторений и всех перестановок, поэтому запрос не возвращается, например, 1+2 и , так как они - одно и то же.

Мы получаем каждое уникальное сочетание как Varchar2 (переименованный в expression ниже), а затем просто извлечь число из этого Varchar2 (как создавать строки со значениями, расщепленных характером +), а затем получить их SUM.

Я выбираю row_number(), упорядоченный по val, так что результаты будут отображаться в порядке, начиная с 1 до последнего номера, независимо от порядка, в котором они были вставлены в базу данных.

Другая проблема заключается в том, что если числа в вашей таблице не уникальны, они будут генерировать дубликаты. Таким образом, это будет работать, только если у вас нет дубликатов в таблице чисел. Если у вас есть дубликаты в таблице, одним из способов исправить это было бы добавить предложение distinct в запросе (я добавил его в код ниже для справки)

Это может быть не лучшее решение, и Я уверен, что есть, вероятно, лучшие альтернативы, но это то, что я мог бы найти в кратчайшие сроки.

Попробуйте:

SELECT distinct expression, 
     ( SELECT SUM (REGEXP_SUBSTR (expression, 
             '[^+]+', 
             1, 
             LEVEL)) 
       FROM DUAL 
      CONNECT BY REGEXP_SUBSTR (expression, 
            '[^+]+', 
            1, 
            LEVEL) 
         IS NOT NULL) 
      AS THE_SUM 
    FROM (WITH t 
       AS ( SELECT ROW_NUMBER() OVER (ORDER BY val) AS seqno, 
          val AS expression 
         FROM my_numbers 
        ORDER BY val ASC), 
       t2 (s, t) 
       AS (SELECT seqno, CAST (expression AS VARCHAR2 (1)) FROM t 
        UNION ALL 
        SELECT t.seqno, t || '+' || expression 
        FROM t, t2 
        WHERE s < seqno) 
      SELECT s, t expression 
      FROM t2) 
ORDER BY 1 

Содержание my_numbers таблицы:

 
VAL 
4 
8 
2 
1 

Выход:

 
EXPRESSION  |  THE_SUM 
1    |  1 
1+2   |  3 
1+2+4   |  7 
1+2+4+8  |  15 
1+2+8   |  11 
1+4   |  5 
1+4+8   |  13 
1+8   |  9 
2    |  2 
2+4   |  6 
2+4+8   |  14 
2+8   |  10 
4    |  4 
4+8   |  12 
8    |  8 
Смежные вопросы