将多个布尔列连接到单个varchar列

时间:2015-11-16 20:19:33

标签: sql postgresql

我正在利用PostgreSQL将数据从一个表转换为另一个表,目前我正在使用布尔列遇到一些挑战。我想将一个带有布尔值的表转换为一个以分号分隔的varchar字段。

以下是我正在执行的两个CREATE TABLE语句。

CREATE TABLE Color_Table
(
"Id" VARCHAR(255),
"IsRed" BOOL,
"IsOrange" BOOL,
"IsYellow" BOOL,
"IsGreen" BOOL,
"IsBlue" BOOL,
"IsIndigo" BOOL,
"IsViolet" BOOL
)

CREATE TABLE Concatenated_Table
(
"Id" VARCHAR(255),
"Semicolon_Colors" VARCHAR(255)
)

以下是我插入Color_Table的示例行。我的期望是将其转化为价值:红色;绿色;靛青;紫;

INSERT INTO Color_Table
(
"Id",
"IsRed",
"IsOrange",
"IsYellow",
"IsGreen",
"IsBlue",
"IsIndigo",
"IsViolet"
) 

VALUES
(
'12345_abcd_67890',
true,
false,
false,
true,
false,
true,
true
)

我试图通过声明它来创建临时变量,并收到错误消息。以下是我尝试使用的脚本/方法。

DECLARE TempVariable VARCHAR(255);
INSERT INTO Concatenated_Table
    (
        "Id",
        "Semicolon_Colors"
    )
SELECT
colors."Id",
BEGIN
    TempVariable = ''

    IF(colors."IsRed" = true)
    BEGIN
        CONCAT(TempVariable, 'Red; ')
    END

    IF(colors."IsOrange" = true)
    BEGIN
        CONCAT(TempVariable, 'Orange; ')
    END

    IF(colors."IsYellow" = true)
    BEGIN
        CONCAT(TempVariable, 'Yellow; ')
    END

    IF(colors."IsGreen" = true)
    BEGIN
        CONCAT(TempVariable, 'Green; ')
    END

    IF(colors."IsBlue" = true)
    BEGIN
        CONCAT(TempVariable, 'Blue; ')
    END

    IF(colors."IsIndigo" = true)
    BEGIN
        CONCAT(TempVariable, 'Indigo; ')
    END

    IF(colors."IsViolet" = true)
    BEGIN
        CONCAT(TempVariable, 'Violet; ')
    END
END
FROM Color_Table colors

对于如何做到这一点,我们非常感谢任何建议!

2 个答案:

答案 0 :(得分:1)

我仍然认为表格设计是一个坏主意,但你应该能够将你的案例连接成一个列 - 就像这样

更新:从mssql更改为Postgres语法:

SELECT
"Id",
CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(
  CASE "IsRed" WHEN true THEN 'Red; ' ELSE '' END,
  CASE "IsOrange" WHEN true THEN 'Red; ' ELSE '' END), 
  CASE "IsYellow" WHEN true THEN 'Yellow; ' ELSE '' END),
  CASE "IsGreen" WHEN true THEN 'Green; ' ELSE '' END),
  CASE "IsBlue" WHEN true THEN 'Blue; ' ELSE '' END),
  CASE "IsIndigo" WHEN true THEN 'Indigo; ' ELSE '' END),
  CASE "IsViolet" WHEN true THEN 'Violet; ' ELSE '' END)
  AS Semicolon_Colors
FROM color_table

备用,更清晰的语法(感谢@a_horse_with_no_name):

SELECT
"Id",    
  CASE WHEN "IsRed" THEN 'Red; ' ELSE '' END ||
  CASE WHEN "IsOrange" THEN 'Red; ' ELSE '' END || 
  CASE WHEN "IsYellow" THEN 'Yellow; ' ELSE '' END ||
  CASE WHEN "IsGreen" THEN 'Green; ' ELSE '' END ||
  CASE WHEN "IsBlue" THEN 'Blue; ' ELSE '' END ||
  CASE WHEN "IsIndigo" THEN 'Indigo; ' ELSE '' END ||
  CASE WHEN "IsViolet" THEN 'Violet; ' ELSE '' END
  AS Semicolon_Colors
FROM color_table

答案 1 :(得分:1)

可以使用concat_ws()简化串联,因为这会处理分隔符;并忽略空值,这意味着case表达式不需要显式{ {1}}部分:

else ''

如果你确实需要保留各个颜色列,我宁愿使用上面的insert into Concatenated_Table ("Id", "Semicolon_Colors") select "Id", concat_ws('; ', case when "IsRed" then 'Red' end, case when "IsOrange" then 'Red' end, case when "IsYellow" then 'Yellow' end , case when "IsGreen" then 'Green' end, case when "IsBlue" then 'Blue' end, case when "IsIndigo" then 'Indigo' end, case when "IsViolet" then 'Violet' end) from Color_Table; 语句创建一个视图,而不是将数据复制到一个新表中。 concat和case语句非常便宜。出于性能原因,无需复制数据。

无关,但是:你应该尽量避免使用带引号的标识符select它们比它们的价值要大得多。 (但是如果你使用它们,那么你应该保持一致,你的表名不要使用带引号的标识符,但是你的列也可以。)