2013-04-04 54 views
3

试图找到一种将CONCAT与IF结合的方法 - 或者以其他方式在逗号分隔列表中显示集合标记的文本值 。MySql:Concat IF'ed values

注意:这最终是一个包含10列以上的表格。在这里使用两个来简化。

说我有一个标志的表。如果标志是1我想显示一些文本值, 否则什么都不是。

origin: 
+--+-----+-----+ 
|# | CHS | ACC | 
+--+-----+-----+ 
|1 | 0 | 1 | 
|2 | 1 | 1 | 
|3 | 1 | 0 | 
|4 | 0 | 0 | 
+--+-----+-----+ 

我想:

+--+----------+ 
|# | origin | 
+--+----------+ 
|1 | ACC  | 
|2 | CHS, ACC | 
|3 | CHS  | 
|4 |   | 
+--+----------+ 

没有(这等):在这个方向

+--+-----------+ 
|# | origin | 
+--+-----------+ 
|1 | ACC,  | 
|2 | CHS, ACC, | 
|3 | CHS,  | 
|4 | ,   | 
+--+-----------+ 

东西:

SELECT 
    CONCAT_WS(', ', 
     IF(CHS = 0, '', 'CHS'), 
     IF(ACC = 0, '', 'ACC') 
    ) as origin 
FROM 
    origin; 

但不能与逗号在空值之间。

这最终是一个有10列的表,我加入了其他基于ID的 。

回答

2

你可以使用CONCAT_WS,即跳过NULL值与CASE组合:

SELECT 
    id, 
    CONCAT_WS(', ', 
    CASE WHEN CHS THEN 'CHS' END, 
    CASE WHEN ACC THEN 'ACC' END 
) as origin 
FROM 
    origin; 

当条件为FALSE时,由于我没有指定ELSE子句,因此CASE将返回NULL值,并且CONCAT_WS将跳过它。您也可以在原始查询中使用NULL而不是“'。

如果你有很多列,你也可以创建一个动态查询像这样的东西:

SELECT 
    CONCAT(
    'SELECT ID, CONCAT_WS(\', \',', 
    GROUP_CONCAT(
     CONCAT(
     'CASE WHEN ', 
     `COLUMN_NAME`, 
     ' THEN \'', 
     `COLUMN_NAME`, 
     '\' END') SEPARATOR ','), 
    ') AS origin FROM origin;' 
    ) 
FROM 
    `INFORMATION_SCHEMA`.`COLUMNS` 
WHERE 
    `TABLE_NAME`='origin' 
    AND COLUMN_NAME!='id' 
INTO @sql; 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 

请参阅小提琴,有两种解决方案,here

+0

太好了。这很好。使用'COLUMN_NAME'使它更好。 – Zimzalabim 2013-04-04 19:20:23

+0

非常有用 - 谢谢! – 2016-04-22 11:40:08

3

有可能是一个更好看的解决方案,但你可以使用

CONCAT(
    IF(CHS = 0, '', 'CHS'), 
    IF(CHS != 0 AND ACC != 0, ', ', ''), 
    IF(ACC = 0, '', 'ACC') 
) 

你也可以使用REPLACE删除“空白”

REPLACE(CONCAT_WS(', ', 
    IF(CHS = 0, 'REMOVEIT', 'CHS'), 
    IF(ACC = 0, 'REMOVEIT', 'ACC') 
), 'REMOVEIT, ', '') 
+0

是的。考虑到,只有10列,它开始看起来很丑陋;) – Zimzalabim 2013-04-04 18:41:51

+0

@Zimzalabim也许我的编辑会有所帮助 – 2013-04-04 18:50:45

+0

谢谢。我需要有多个REPLACE语句,(或者找到另一种删除所有REMOVEIT的聪明方法),我正在查看它。 – Zimzalabim 2013-04-04 19:12:45

1

试试这个。

SELECT 
    TRIM(TRAILING ', ' FROM CONCAT_WS(', ', 
     IF(CHS = 0, '', 'CHS'), 
     IF(ACC = 0, '', 'ACC') 
    )) as origin 
FROM 
    origin; 

这里是mysql文档。

http://dev.mysql.com/doc/refman/5.5/en/string-functions.html#function_trim

+0

谢谢。虽然这对3列以上不太好,但它是有价值的信息。 – Zimzalabim 2013-04-04 19:23:22

+0

如果架构在您的控制中,我建议您将列名称作为值放入单独的表中,并使用原始表中的外键引用来简化操作。这还允许您通过插入行而不是向原始表中添加更多列来即时添加更多值。 – Slowcoder 2013-04-04 21:51:46