Mam następujące dwie tabele:

Śpiewacy

identification    name
-------------------------
      20          Bolton
      21          Madonna
      22          Nirvana
      23          Hendrix

Kolaborowany

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

Chcę uzyskać wynik, gdzie każde imię tabeli śpiewaków stwierdził w drugiej kolumnie, czy śpiewają metal. Tak więc na przykład Hendrix i Madonna śpiewa metal, więc stół powinien wyglądać tak:

name     metal
--------------
Bolton   N
Madonna  Y
Nirvana  N
Hendrix  Y

Próbowałem następujących, ale nie otrzymuję różnych wyników ani nie uwzględnia symetrycznej relacji kolablorowej.

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

Jak mogę rozwiązać to z wyrażeniem sprawy?

sql
1
Ozera 14 kwiecień 2021, 22:11

3 odpowiedzi

Najlepsza odpowiedź

Możesz ustalić tę liczbę sposobów, w jedną stronę użyto exists

Select name,
  case when exists (select * from colaborate c where c.first_singer_id=s.identification and genre='metal')
         or exists (select * from colaborate c where c.second_singer_id=s.identification and genre='metal')
  then 'Y' else 'N' end as Metal
from Singers s
2
Stu 14 kwiecień 2021, 19:19

First_singer_id, drugi_singer_id, ... wskazuje, że schemat można zrobić lepiej. Co się stanie, jeśli trzeci współpracują? Lub Trzydzieści?

Listy w SQL są wykonywane za pomocą tabel łączących. Jeśli zrestrukturytujesz swoje dane, tak jak ...

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)
);

Teraz możesz mieć jak wielu śpiewaków na piosenkę, jak chcesz. Nadal musisz agregować powstałe wiersze, a Technika Forpasa działa dobrze, ale bez dołączenia dołączenia.

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

Spróbuj go.

0
Schwern 14 kwiecień 2021, 20:05

Dołącz do tabel za pomocą LEFT dołącz i użyj agregacji warunkowej:

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
1
forpas 14 kwiecień 2021, 19:20