Sql 返回包含“是”或“否”列的表

Sql 返回包含“是”或“否”列的表,sql,Sql,我有以下两个表格: 歌手 identification name ------------------------- 20 Bolton 21 Madonna 22 Nirvana 23 Hendrix 协同工作 first_singer_id second_singer_id genre ------------------------------

我有以下两个表格:

歌手

identification    name
-------------------------
      20          Bolton
      21          Madonna
      22          Nirvana
      23          Hendrix
协同工作

first_singer_id     second_singer_id       genre
---------------------------------------------------
      20                  21               pop
      21                  23               pop
      22                  21               rock
      23                  20               rock
      23                  21               metal
      23                  21               hiphop
      23                  22               pop
我想得到一个结果,歌手表中的每个名字都在第二列中说明他们是否唱金属歌。比如亨德里克斯和麦当娜唱《金属》,所以桌子应该是这样的:

name     metal
--------------
Bolton   N
Madonna  Y
Nirvana  N
Hendrix  Y
我尝试了以下方法,但没有得到明确的结果,也没有考虑到Colaborate的对称关系

select case when C.genre= 'metal' then "Y" else "N" end as genre, S1.name 
from   Colaborate C
       JOIN Singers S1
       ON S1.identification = C.first_singer_id
       JOIN Singers S2
       ON S2.identification = C.second_singer_id

如何用CASE表达式来解决这个问题?

您可以通过多种方法来确定这一点,其中一种方法是使用exists


您可以通过多种方式确定这一点,其中一种方式是使用exists

使用左联接联接表并使用条件聚合:

SELECT s.name,
       MAX(CASE WHEN c.genre = 'metal' THEN 'Y' ELSE 'N' END) metal
FROM Singers s LEFT JOIN Colaborate c
ON s.identification IN (c.first_singer_id, c.second_singer_id)
GROUP BY s.identification, s.name
使用左联接联接表并使用条件聚合:

SELECT s.name,
       MAX(CASE WHEN c.genre = 'metal' THEN 'Y' ELSE 'N' END) metal
FROM Singers s LEFT JOIN Colaborate c
ON s.identification IN (c.first_singer_id, c.second_singer_id)
GROUP BY s.identification, s.name

第一个歌手身份证,第二个歌手身份证。。。表示架构可以做得更好。如果三个歌手合作会怎么样?还是

SQL中的列表是通过联接表完成的。如果你像这样重组你的数据

create table songs (
  id bigint primary key generate always as identity,
  name text not null,
  genre text not null
);

create table singers (
  id bigint primary key generate always as identity,
  name text not null
);

create table song_singers (
  song_id bigint not null references songs(id),
  singer_id bigint not null references singers(id)
);
现在,每首歌可以有任意多的歌手。您仍然需要聚合结果行和,但不需要自联接

select
  singers.name,
  max(case songs.genre when 'metal' then 'Y' else 'N' end) as genre
from singers
left join song_singers on singers.id = song_singers.singer_id
left join songs on songs.id = song_singers.song_id
group by singers.id

.

第一个歌手id,第二个歌手id。。。表示架构可以做得更好。如果三个歌手合作会怎么样?还是

SQL中的列表是通过联接表完成的。如果你像这样重组你的数据

create table songs (
  id bigint primary key generate always as identity,
  name text not null,
  genre text not null
);

create table singers (
  id bigint primary key generate always as identity,
  name text not null
);

create table song_singers (
  song_id bigint not null references songs(id),
  singer_id bigint not null references singers(id)
);
现在,每首歌可以有任意多的歌手。您仍然需要聚合结果行和,但不需要自联接

select
  singers.name,
  max(case songs.genre when 'metal' then 'Y' else 'N' end) as genre
from singers
left join song_singers on singers.id = song_singers.singer_id
left join songs on songs.id = song_singers.song_id
group by singers.id

.

请使用数据库平台标记这在具有规范化数据的关系数据库中会更容易-如果您将协作表重新构造为具有song_id和流派列的歌曲,然后添加另一个具有song_id和singer_id列的表song_singers。然后您可以仅使用联接来执行此操作,不需要额外的GROUP BY或其他子查询。请使用数据库平台标记这在具有规范化数据的关系数据库中会更容易-如果您将协作表重新构造为包含song_id和GREEP列的songs,然后添加另一个表song_singers,其中包含song_id和singer_id列。然后,您可以仅使用联接来执行此操作,无需额外的分组依据或其他子查询。因为它是主键,所以可以按s.identification进行分组。@Schwern是的,它是主键,但是名称也应该返回,这就是为什么它必须包含在GROUPBY子句中。您能解释一下SELECT中的MAX逻辑吗?严格说来,这行得通吗?我明白。因为s.identification是主键,它是唯一的,所以不必在group by中有s.name来在select中使用它。@WOUNDEDStevenJones完全正确。因为它是主键,所以可以通过s.identification进行分组。@Schwern是的,它是主键,但是名称也应该返回,这就是为什么它必须包含在GROUPBY子句中。您能解释一下SELECT中的MAX逻辑吗?严格说来,这行得通吗?我明白。因为s.identification是主键,它是唯一的,所以在选择中使用s.name不必在group by中。@WOUNDEDStevenJones完全正确。有了正确的索引,这可能是最快的方法。有了正确的索引,这可能是最快的方法。