如何在postgres中按行和值选择列?

时间:2016-11-04 11:31:16

标签: sql bash postgresql

我有一个这样的表,值都是布尔值,除了col1,这些是rownames(主键):

col1 | col2 | col3 | col4 | col5 ...
-------------------------------- 
row1 | f    | t    | t    | t    
row2 | f    | f    | f    | t    
row3 | t    | f    | t    | f    
:

我想要一个这样的查询: select all columns for row3 where value=t ,或者更准确地说: select all column-names for row3 where value=t
在这个例子中,答案应该是:

col2
col4

因为我知道所有列名,我可以通过调用者中的递归来实现,我的意思是,例如通过从bash调用postgres-client,对我感兴趣的每一行的colums进行递归。但是postgres-sql中是否有解决方案?

2 个答案:

答案 0 :(得分:3)

这不是SQL的工作原理。 SQL适用于,而非列。

这表明您的数据结构是错误的。相反,如果您将值存储在如下行中:

col1    name      value
row1    'col1'    value
. . .

然后你会这样做:

select name
from t
group by name
having count(*) = sum(case when value then 1 else 0 end);

使用您的结构,您需要为每列执行单独的子查询。像这样:

select 'col2'
from yourtable
having count(*) = sum(case when col2 then 1 else 0 end)
union all
select 'col3'
from yourtable
having count(*) = sum(case when col3 then 1 else 0 end)
union all
. . .

答案 1 :(得分:0)

我不是在这里试图回答你的问题,而是想告诉你哪种数据库结构适合所描述的任务。

  • 你有一本带有书名的书桌。每条记录都包含一本书。
  • 您有一个带有单词ID的单词表。每条记录都包含一个单词。
  • 现在您想要一个包含所有现有图书 - 单词组合的列表。

您为此关系创建的表称为桥表。一本书可以包含很多单词;许多书中都可以包含一个词;一个n:m的关系。该表有两列:book id和word id。这两个组合是表的主键(复合键)。每条记录都包含一本现有的书和单词组合。

以下是如何使用此表的一些示例:

查找书中包含的所有单词:

select word
from words
where word_id in
(
  select word_id
  from book_word
  where book_id = 
  (
    select book_id 
    from books 
    where name = 'Peter Pan'
  )
);

(这只是一个例子;连接而不是子查询可以得到相同的结果。)

选择两本特定书籍中的单词:

select word
from words
where word_id in
(
  select word_id
  from book_word
  where book_id in
  (
    select book_id 
    from books 
    where name in ('Peter Pan', 'Treasure Island')
  )
  group by word_id
  having count(*) = 2
);

查找仅在一本书中出现的单词:

select w.word, min(b.name) as book_name
from words w 
join book_word bw on bw.word_id = w.word_id
join books b on b.book_id = bw.book_id
group by w.word_id
having count(*) = 1;