Postgres / pgadmin3 - 为给定行选择等于true的所有列

时间:2016-08-02 18:31:23

标签: sql database postgresql

我不确定如何做到这一点,但我必须选择给定行中的所有列,其中值等于布尔值TRUE。

Columns: |  X   |  Y    |  Z   |  A   |
0        | TRUE | FALSE | TRUE | TRUE |

在这种情况下,我需要一个返回的SQL语句:

Columns: |  X   |  Z   |  A   |
0        | TRUE | TRUE | TRUE |

我在一个表中执行此操作,该表的大小不会发生变化(基本上是静态的),大约有250列和220行。

最终,我将需要一个语句,它返回TRUE的列名,基本上是:

0       |  X   |  Z   |  A   |

非常感谢任何帮助!

编辑1

根据下面的Nicarus解决方案,我想出了以下内容:

WITH i (A, B, C)
AS (
SELECT attributes.A, B, C
FROM (attributes JOIN contexts ON attributes.A = contexts.A)
WHERE context_full_name = 'Print book'
),
i_sub AS (
SELECT 
    A,
    UNNEST(ARRAY['B', 'C']) 
        AS col_name,
    UNNEST(ARRAY[B, C]) 
        AS col_value
FROM i)
SELECT STRING_AGG(col_name, ',') AS true_col_names INTO temporary_table
FROM i_sub WHERE col_value = TRUE GROUP BY A;

SELECT * FROM temporary_table;

但是,我返回的结果是最终的select语句错误...

我使用以下方式进行了双重检查:

SELECT *
FROM (attributes JOIN contexts ON attributes.attribute_id = contexts.attribute_id)
WHERE context_full_name = 'Print book';

这个专栏肯定是假的......

我弄乱了什么吗?

编辑2

因此,EDIT 1中的查询试图实现以下目标;改变这个:

Columns: |  X   |  Y    |  Z   |  A   |
0        | TRUE | FALSE | TRUE | TRUE |
1        | TRUE | TRUE  | TRUE | FALSE|
2        | FALSE| FALSE | TRUE | FALSE|

在这种情况下,我需要一个返回的SQL语句:

Columns: |  X   |  Z   |  A   |
0        | TRUE | TRUE | TRUE |

相反,它会返回所有具有真值的列:

Columns: |  X   |  Y    |  Z   |  A   |
0        | TRUE | TRUE  | TRUE | TRUE |

我的实施

这绝不是最有效率的,但它对我想要实现的目标起作用:

SELECT attributes.attribute_id, context_full_name, A, B, C, D
INTO TEMP j
FROM (attributes JOIN contexts ON attributes.attribute_id = contexts.attribute_id)
WHERE contexts.context_full_name = 'Print book' LIMIT 1;

WITH i_sub AS (
    SELECT
        attribute_id,
        context_full_name,
        UNNEST(ARRAY[A, B, C, D]) AS col_value
    FROM j)
SELECT ROW_NUMBER() OVER () as rn, *
INTO TEMP temporary_table
FROM i_sub;

SELECT context_full_name, attribute_id, temporary_table.rn, temporary_table.col_value, attribute_titles.attribute_name_column, attribute_titles.attribute_names
INTO TEMP result
FROM
(temporary_table JOIN attribute_titles -- attribute titles is a table I created which lists the column headers in the same order as they are in the attributes table, so that the row number on the temporary_table equals the attribute_titles column "attribute_name_id".
ON temporary_table.rn = attribute_titles.attribute_name_id) WHERE col_value = TRUE;

SELECT * FROM result; -- This prints the list with the attribute_id, context_full_name, the column value where TRUE (to check to make sure it worked), the column names shown in attribute_titles, and the attribute names (plaintext versions). This table can be further manipulated as necessary.

1 个答案:

答案 0 :(得分:1)

我不是100%肯定你的用例;但是,您可以返回其值为TRUE的列名称的“列表”。这只是一种方法。

这里我“解锁”数据,过滤掉任何FALSE条记录,然后连接列名称以返回每行一条记录。您也可以决定使数据更规范化(不连接列名)

WITH mytable (row_id,X,Y,Z,A) AS
(
VALUES
    (1,TRUE,TRUE,TRUE,FALSE),
    (2,TRUE,FALSE,TRUE,FALSE),
    (3,FALSE,TRUE,TRUE,TRUE)
),

mycte AS
(
SELECT
    row_id,
    UNNEST(ARRAY['X','Y','Z','A']) AS col_name,
    UNNEST(ARRAY[X,Y,Z,A]) AS col_value
FROM
    mytable
)

SELECT
    row_id,
    STRING_AGG(col_name,'|') AS true_col_names
FROM
    mycte
WHERE
    col_value
GROUP BY
    row_id;

你说你仍然有问题,但我不清楚它们是什么。

我使用了您的查询(使用我的测试数据),我得到了这个:

DROP TABLE IF EXISTS temporary_table;

WITH i (A,B,C) AS
(
VALUES
    (TRUE,TRUE,FALSE),
    (FALSE,TRUE,FALSE),
    (TRUE,TRUE,TRUE)
),

i_sub AS (
SELECT 
    A,
    UNNEST(ARRAY['B', 'C']) 
        AS col_name,
    UNNEST(ARRAY[B, C]) 
        AS col_value
FROM i)

SELECT
    STRING_AGG(col_name, ',') AS true_col_names,
    STRING_AGG(DISTINCT col_name, ',') AS true_col_names_unique --only unique col_names
INTO
    temporary_table
FROM
    i_sub
WHERE
    col_value;

SELECT * FROM temporary_table;

输出:

enter image description here