문제

두 개의 기본 테이블이있는 데이터베이스가 있습니다 notes 그리고 labels. 그들은 다수의 관계를 가지고 있습니다 (StackoverFlow.com이 레이블과의 질문이있는 방법과 유사합니다). 내가 궁금한 점은 SQL을 사용하여 여러 라벨을 사용하여 메모를 어떻게 검색 할 수 있습니까?

예를 들어 3 개의 레이블 "One", "Two"및 "Three"가있는 노트 "테스트"가있는 경우 "One"및 "Two"라벨이있는 두 번째 음표 "Test2"가 있습니다. 레이블 "One"및 "Two"와 관련된 모든 메모를 찾으십니까?

도움이 되었습니까?

해결책

가지고있는 메모의 세부 사항을 얻습니다 둘 다 라벨 'one'및 'two':

select * from notes
where note_id in
( select note_id from labels where label = 'One'
  intersect
  select note_id from labels where label = 'Two'
)

다른 팁

참고 : 실제로 이것을 테스트하지 않았습니다. 또한 Notes_Labels라는 다수의 테이블이 있다고 가정합니다.

라벨을 가지고 있다는 음표 만 원한다면 이와 같은 것입니다.

SELECT DISTINCT n.id, n.text
FROM notes n
INNER JOIN notes_labels nl ON n.id = nl.note_id
INNER JOIN labels l ON nl.label_id = l.id
WHERE l.label IN (?, ?)

모든 레이블이있는 메모를 원한다면 약간의 추가 작업이 있습니다.

SELECT n.id, n.text
FROM notes n
INNER JOIN notes_labels nl ON n.id = nl.note_id
INNER JOIN labels l ON nl.label_id = l.id
WHERE l.label IN (?, ?)
GROUP BY n.id, n.text
HAVING COUNT(*) = 2;

? SQL 자리 표시자가되고 2는 당신이 찾고있는 태그 수입니다. 이것은 링크 테이블에 복합 기본 키로 ID 열을 모두 가지고 있다고 가정합니다.

select * from notes a
inner join notes_labels mm on (mm.note = a.id and mm.labeltext in ('one', 'two') )

물론, 실제 열 이름으로 바꾸십시오. 테이블에 대한 나의 가정이 정확하기를 바랍니다.

그리고 실제로 영어 덕분에 당신의 질문에 약간의 모호성이 있습니다. 그리고 단어 '와' '라는 단어가 때때로 어떻게 사용되는지. 예를 들어, '하나'가 아닌 '2'가 아닌 메모를보고 싶다면, 이것은 작동해야합니다 (당신의 해석 '및' 'one'및/plus로 모든 메모를 보여줍니다. 레이블이 'Two'라는 노트). 그러나 두 레이블이 모두있는 메모 만 원한다면 이것이 한 가지 방법이 될 것입니다.

select * from notes a
where exists (select 1 from notes_labels b where b.note = a.id and b.labeltext = 'one')
     and exists (select 1 from notes_labels c where c.note = a.id and c.labeltext = 'two')

편집 : 모든 제안에 감사드립니다. 내 뇌의 월요일 기어는 조금 느립니다 ... 내가 위키를해야했던 것 같습니다!

이런 것 ... (다른 링크 테이블이 필요합니다)

SELECT *
FROM Notes n INNER JOIN NoteLabels nl
ON n.noteId = nl.noteId
WHERE nl.labelId in (1, 2)

편집하다: Notelabel 테이블에는 Composite PK가있는 NoteID 및 LabelId의 두 개의 열이 있습니다.

정규화 된 데이터베이스가 있다고 가정하면 사이에 다른 테이블이 있어야합니다. notes 그리고 labels

그런 다음 An을 사용해야합니다 inner join 테이블을 함께 연결합니다

  1. 가입하십시오 labels 바인드 테이블이있는 테이블 (다수의 테이블)
  2. 가입하십시오 notes 이전 쿼리가있는 테이블

예시:

select * from ((labels l inner join labels_notes ln on l.labelid = ln.labelid) inner join notes n on ln.notesid = n.noteid)

그렇게하면 두 테이블을 모두 연결했습니다.

이제 추가해야 할 것은 where 조항 ... 그러나 나는 그것을 당신에게 맡길 것입니다.

당신은이 다수의 관계가 어떻게 실현되는지에 대해 아무 말도하지 않습니다. 레이블 테이블에 레이블이있는 것으로 가정합니다 (noteid : int, label : varchar) - 기본 키는 둘 다에 걸쳐 있습니까?

SELECT DISTINCT n.id from notes as n, notes_labels as nl WHERE n.id = nl.noteid AND nl.text in (label1, label2);

열 이름으로 교체하고 레이블에 적절한 자리 표시자를 삽입하십시오.

목록이 필요한 경우 사용할 수 있습니다. where exists 복제를 피하기 위해. 선택 기준에서 노드에 대해 여러 개의 태그가있는 경우 결과에서 중복 행이 나타납니다. 다음은 다음과 같습니다 where exists:

create table notes (
       NoteID int not null primary key
      ,NoteText varchar (max)
)
go

create table tags (
       TagID int not null primary key
      ,TagText varchar (100)
)
go

create table note_tag (
       NoteID int not null
      ,TagID int not null
)
go

alter table note_tag
  add constraint PK_NoteTag
      primary key clustered (TagID, NoteID)
go

insert notes values (1, 'Note A')
insert notes values (2, 'Note B')
insert notes values (3, 'Note C')

insert tags values (1, 'Tag1')
insert tags values (2, 'Tag2')
insert tags values (3, 'Tag3')

insert note_tag values (1, 1) -- Note A, Tag1
insert note_tag values (1, 2) -- Note A, Tag2
insert note_tag values (2, 2) -- Note B, Tag2
insert note_tag values (3, 1) -- Note C, Tag1
insert note_tag values (3, 3) -- Note C, Tag3
go

select n.NoteID
      ,n.NoteText
  from notes n
 where exists
       (select 1
          from note_tag nt
          join tags t
            on t.TagID = nt.TagID
         where n.NoteID = nt.NoteID
           and t.TagText in ('Tag1', 'Tag3'))


NoteID      NoteText
----------- ----------------
1           Note A
3           Note C
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top