Я пытаюсь сделать сумму в столбце, который зависит от столбцов, прежде чем быть 1 - PullRequest
0 голосов
/ 17 апреля 2019

У меня есть 12 столбцов, которые имеют ЛИБО '1' или '0'.Я хочу сделать сумму по первому столбцу из всех.Затем, если в первом столбце были все «1», то я хочу получить сумму всех «1» в столбце 2. Затем, если все столбцы 1 и 2 были «1», я хочу получить суммувсе «1» в столбце 3. и т. д. Я пытаюсь сделать это в случаях, как показано ниже.Тем не менее, он работает нормально, только до столбца 3, после столбца 4 я получаю только NULL.

SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1  THEN  1  END ) TOTAL_MONTH_1,
SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1  THEN 1  END )TOTAL_MONTH_2,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 THEN  1  END ) TOTAL_MONTH_3,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 THEN  1  END ) TOTAL_MONTH_4,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 AND  MAX(B.PREVIOUS_5) = 1 THEN  1  END ) TOTAL_MONTH_5

Я ожидаю получить

column 1   column 2   column 3....... 
1            1        0
0            1        1
1            0        0

результат:

2            1        0

Ответы [ 5 ]

3 голосов
/ 17 апреля 2019

Хорошо, должен признать, этот вопрос меня заинтриговал!Я отвечаю, потому что я ненавижу идею SQL-запроса, длина текста которого основана на квадрат числа столбцов.Потому что, честно говоря, у вас будет 72 случая, если у вас есть 12 столбцов (12 * 12/2).Такой код ужасно поддерживать и ужасно модифицировать.

Итак, я подойду к этому как математическая головоломка.Допустим, есть только два столбца: a и b.Если a = 0, ответ 0;если a = 1, ответ равен 1, если b = 0, и 2, если b = 1.Ну, это довольно просто: ответ: a * (a + b).Если a = 0, вы умножаете некоторое число на 0, что будет равно нулю.

Или мы можем даже быть более любопытными - мы можем сказать, что это a * (1 + b) - в любом случае работает, и этоКстати, у нас на изображении только один «а».

Answer(a,b) = a*(1+b)

Хорошо, а как насчет третьего столбца?

Теперь у нас есть a, b и c.Если a = 0, наш ответ по-прежнему равен нулю.Но если a = 1, наш ответ должен быть 1 + ответ (b, c).

Answer(a,b,c) = a*(1+Answer(b,c))
Answer(a,b,c) = a*(1+b*(1+c)

Имеет ли это смысл?И теперь, когда мы знаем это, закономерность довольно очевидна:

Answer(a,b,c,d,....) = a*(1+b*(1+c*(1+d* ...

Хорошо - так как мы смотрим с точки зрения длины?Каждый термин - каждый столбец - используется только один раз .Если у вас есть 12 столбцов, у вас будет только 12 терминов!Не 72!(Плюс, это довольно легко расширить, включив в него еще несколько столбцов.)

Еще лучше, действительно просто получить суммы каждого «столбца» в этой точке.В конце концов, ваши данные будут выглядеть так:

ColA,ColB,ColC,ColD,KevinsAnswer
0    1    0    0    0
1    1    0    1    2
1    1    1    1    4
0    0    1    0    0
1    0    0    0    1
1    1    1    0    3

Если вы хотите узнать, сколько строк имеют по крайней мере два 1?Получите сумму () где KevinsAnswer> = 2.

Так что мой окончательный ответ будет примерно таким (я извиняюсь, если здесь есть какие-то не-оракульные команды; мой опыт - MS SQL)

select StraightMonths,Count(*) from
(
    select B.PREVIOUS_1 *
        (1 + B.PREVIOUS_2 *
        (1 + B.PREVIOUS_3 *
        (1 + B.PREVIOUS_4 *
        (1 + B.PREVIOUS_5 *
        (1 + B.PREVIOUS_6 *
        (1 + B.PREVIOUS_7 *
        (1 + B.PREVIOUS_8 *
        (1 + B.PREVIOUS_9 *
        (1 + B.PREVIOUS_10 *
        (1 + B.PREVIOUS_11 *
        (1 + B.PREVIOUS_12 ))))))))))) as StraightMonths
    ) as straightMonthsSubquery
) group by StraightMonths

... а затем используя , что , как подзапрос, чтобы получить конкретный интересующий вас месяц;просто запомните, если вы хотите, чтобы month = 2, вы должны SUM () значения для StraightMonths> = 2 (значение в записи 2 - это только те, которые имели ровно два месяца.) Или даже простопоместите эти данные из запроса в таблицу temp / variable (в ней всего 12 строк с одним столбцом.)

1 голос
/ 17 апреля 2019

Поскольку CASE работает как пробой, вы можете сделать что-то вроде следующего:

select CASE when column1=0 then 0
            when column2=0 then 1
            when column3=0 then 2
            when column4=0 then 3
            ...
            when column12=0 then 11
            else 12
        END as ONES_COUNT

Это будет работать, потому что у вас есть только двоичная опция для каждого столбца - это может быть либо 1, либо 0. Если это 0, то вам следует прекратить считать и вернуть предыдущее значение. Если это 1, вы должны перейти к следующему случаю и повторять, пока не получите значение.

0 голосов
/ 17 апреля 2019

Это решение, которое я получил, и оно сработало.Кстати, причина MAX заключается в том, что он исходит из результата в подзапросе.

SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1  THEN  1  ELSE 0 END ) TOTAL_MONTH_1,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1  THEN 1  ELSE 0 END )TOTAL_MONTH_2,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 THEN  1  ELSE 0 END ) TOTAL_MONTH_3,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 THEN  1  ELSE 0 END ) TOTAL_MONTH_4,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 AND  MAX(B.PREVIOUS_5) = 1 THEN  1 ELSE 0   END ) TOTAL_MONTH_5,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 AND  MAX(B.PREVIOUS_5) = 1 AND  MAX(B.PREVIOUS_6) = 1 THEN  1 ELSE 0   END ) TOTAL_MONTH_6,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 AND  MAX(B.PREVIOUS_5) = 1 AND  MAX(B.PREVIOUS_6) = 1 AND  MAX(B.PREVIOUS_7) = 1  THEN  1 ELSE 0   END ) TOTAL_MONTH_7,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 AND  MAX(B.PREVIOUS_5) = 1 AND  MAX(B.PREVIOUS_6) = 1 AND  MAX(B.PREVIOUS_7) = 1 AND  MAX(B.PREVIOUS_8) = 1 THEN  1 ELSE 0   END ) TOTAL_MONTH_8,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 AND  MAX(B.PREVIOUS_5) = 1 AND  MAX(B.PREVIOUS_6) = 1 AND  MAX(B.PREVIOUS_7) = 1 AND  MAX(B.PREVIOUS_8) = 1 AND  MAX(B.PREVIOUS_9) = 1 THEN  1 ELSE 0   END ) TOTAL_MONTH_9,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 AND  MAX(B.PREVIOUS_5) = 1 AND  MAX(B.PREVIOUS_6) = 1 AND  MAX(B.PREVIOUS_7) = 1 AND  MAX(B.PREVIOUS_8) = 1 AND  MAX(B.PREVIOUS_9) = 1 AND  MAX(B.PREVIOUS_10) = 1 THEN  1 ELSE 0   END ) TOTAL_MONTH_10,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 AND  MAX(B.PREVIOUS_5) = 1 AND  MAX(B.PREVIOUS_6) = 1 AND  MAX(B.PREVIOUS_7) = 1 AND  MAX(B.PREVIOUS_8) = 1 AND  MAX(B.PREVIOUS_9) = 1 AND  MAX(B.PREVIOUS_10) = 1 AND  MAX(B.PREVIOUS_11) = 1 THEN  1 ELSE 0   END ) TOTAL_MONTH_11,
    SUM (CASE WHEN MAX(B.PREVIOUS_1) = 1 AND  MAX(B.PREVIOUS_2) = 1 AND  MAX(B.PREVIOUS_3) = 1 AND  MAX(B.PREVIOUS_4) = 1 AND  MAX(B.PREVIOUS_5) = 1 AND  MAX(B.PREVIOUS_6) = 1 AND  MAX(B.PREVIOUS_7) = 1 AND  MAX(B.PREVIOUS_8) = 1 AND  MAX(B.PREVIOUS_9) = 1 AND  MAX(B.PREVIOUS_10) = 1 AND  MAX(B.PREVIOUS_11) = 1 AND  MAX(B.PREVIOUS_12) = 1 THEN  1 ELSE 0   END ) TOTAL_MONTH_12
0 голосов
/ 17 апреля 2019

Я бы использовал least() с sum():

select sum(col1),
       sum(least(col1, col2)),
       sum(least(col1, col2, col3)),
       . . .
from t;

Другой метод:

select sum(case when pos <= 1 then 1 else 0 end),
       sum(case when pos <= 2 then 1 else 0 end),
       sum(case when pos <= 3 then 1 else 0 end),
       . . .
from (select t.*,
             instr(col1 || col2 || col3 . . . || '0', '0') as pos
      from t
     ) t;

Это вычисляет позицию первого 0 в каждой строке и использует ее для агрегации.

0 голосов
/ 17 апреля 2019

с вашим кодом все в порядке, вам просто нужно добавить еще 0 во все операторы case, также, поскольку вы сравниваете на основе одного наблюдения, поэтому я думаю, что MAX не нужен, просто сравните столбцы, как показано ниже:

   sum(column1) as total_month_1,
   sum(case when column1=1 and column2=1 then 1 else 0 end) total_month_2,
   sum(case when column1=1 and column2=1 and column3=1 then 1 else 0 end) total_month_3
   sum(case when column1=1 and column2=1 and column3=1 and column4=1 then 1 else 0 end) total_month_4
   sum(case when column1=1 and column2=1 and column3=1 and column4=1 and column5=1 then 1 else 0 end) total_month_5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...