我有一个这样的表,值都是布尔值,除了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中是否有解决方案?
答案 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)
我不是在这里试图回答你的问题,而是想告诉你哪种数据库结构适合所描述的任务。
您为此关系创建的表称为桥表。一本书可以包含很多单词;许多书中都可以包含一个词;一个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;