【问题标题】:Postgres/pgadmin3 - Selecting all columns equal to true for a given rowPostgres/pgadmin3 - 为给定行选择等于 true 的所有列
【发布时间】:2016-08-04 01:40:35
【问题描述】:

我不确定如何执行此操作,但我必须选择给定行中值等于布尔值 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 *
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.

【问题讨论】:

  • 同一列中的TRUEFALSE 值是否对所有行都相同?意思是,对于所有行,X 始终为 TRUE 或始终为 FALSE
  • 不,他们并不抱歉。虽然我一次只使用一行,所以我可以创建一个只有一行的临时子表? (这样子表中的所有行都相同?)
  • 您没有选择列。您选择行。匹配行中的列然后被投影。因此,在这种情况下,这意味着由于每一行可能具有不同的真/假列值组合组合,因此每一行在结果集中将具有不同的结构。那不可能发生。结果集是一个表结构。按列行。查询结果集中的每一行不能有不同的列。

标签: sql database postgresql


【解决方案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;

输出:

【讨论】:

  • 目前正在使用此解决方案,但我可以传递一行的 SELECT 语句而不是答案开头指定的 VALUES 子句吗?
  • 是的,您可以用自己的 SELECT 替换 VALUES...
  • @user3684314 使用hstore 扩展名更简单一点:... select akeys(hstore(mytable) - hstore('x=>f,y=>f,z=>f,a=>f')) from mytable;
  • @Nicarus 我用我尝试过的代码实现更新了这个问题(为了简单起见,我替换了列名,但其他一切都是一样的)。我返回了一些错误的列。
  • @user3684314 - 你能确认B、C等列的数据类型真的是BOOLEAN而不是TEXT吗?
猜你喜欢
  • 2011-11-07
  • 2018-07-08
  • 1970-01-01
  • 2023-01-18
  • 1970-01-01
  • 2021-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多