Несколько THEN для одного и того же условия CASE с объединением в MySQL - PullRequest
0 голосов
/ 04 ноября 2019

У меня есть таблица с данными, похожими на

  table : foo
 ---------------------------------
 id  | A1 | B1 | C1 | D1 | A2 | B2 | ........ so on
 ----------------------------------
 abc | 2  | 4  | 6  | 7  | 3  | 4  |......... so on
 -----------------------------------

Требуется вывод

 id  |  Value
 ------------
 abc |  2  |
 abc |  4  |
 abc |  6  | 
 abc |  7  |
 abc |  3  |
 abc |  4  |

   ....and so on

Запрос, который я подготовил

 select case when id='abc' then A1 else 0 end from foo 
 union all
 select case when id='abc' then B1 else 0 end from foo
 union all
 select case when id='abc' then C1 else 0 end from foo
 union all
 select case when id='abc' then D1 else 0 end from foo
 union all
 select case when id='abc' then A2 else 0 end from foo
 union all
 select case when id='abc' then b2 else 0 end from foo 

 .... and so on

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

Ответы [ 2 ]

1 голос
/ 04 ноября 2019

Как уже предложено P.Salmon .

Нам нужно использовать динамический sql и знать, из какого столбца возвращается значение, вы также можете добавить имя столбца в операторе select.

Запрос:

select 
    group_concat(concat("select id, '", column_name, "' as col_name, case when id = 'abc' then ", 
        column_name, " else 0 end as col_value from foo") 
        separator '\nunion all\n') 
        into @pivotcol
from (select column_name from information_schema.columns 
        where table_name  = 'foo' and column_name <> 'id') t;

prepare stmt from @pivotcol;
execute stmt;
deallocate prepare stmt;

Результат:

id  | col_name | col_value
:-- | :------- | --------:
abc | A1       |         2
abc | B1       |         4
abc | C1       |         6
abc | D1       |         7
abc | A2       |         3
abc | B2       |         4

db <> скрипка здесь

1 голос
/ 04 ноября 2019
You don't need a case statement for this
drop table if exists t,t1;

create table t(id varchar(3),a int,b int, c int);

insert into t values
('abc',1,2,3),('def',4,5,6);

select id,a value from t
union all
select id,b from t
union all
select id,c from t
order by id;

+------+-------+
| id   | value |
+------+-------+
| abc  |     1 |
| abc  |     2 |
| abc  |     3 |
| def  |     4 |
| def  |     5 |
| def  |     6 |
+------+-------+
6 rows in set (0.00 sec)

НО у вас потенциально есть проблемы - с вашим дизайном вы не можете определить, какая строка пришла из столбца a (столбец b, столбец c и т. Д.).

Чтобы принудительно упорядочить строки в порядке столбцов (слева направо), вам понадобится столбец, в котором будет храниться порядковый номер, чтобы вы могли упорядочить по нему

select id,1 as col,a value from t
union all
select id,2,b from t
union all
select id,3,c from t
order by id,col;

Игнорирование проблем дляТеперь, если вы можете изменить количество столбцов и не хотите перекодировать, тогда используйте подготовленные операторы, возможно, в процедуре можно сделать https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-prepared-statements.html

set @sql = 
( 
select group_concat(
         concat('select id,', column_name, ' as value from t union all ')
         )
from
(
select table_name,column_name
from information_schema.columns
where table_name = 't' and table_schema = 'sandbox' and column_name <> 'id'
) s
);

set @sql = (select replace(concat(substring(@sql,1,length(@sql) - 11),';'),',select','select'));

prepare sqlstmt from @sql;
execute sqlstmt;
deallocate prepare sqlstmt;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...