我有一个数据库有两个主要表 noteslabels.他们有许多对多关系(类似于如何stackoverflow.com 有问题与标签)。什么我不知道是怎么我可以寻找一个注意使用多个标签使用SQL?

例如,如果我有注意"测试"与三个标签"one","two",并"三"我有一个第二意"测试2"标签"一"和"两个"是什么SQL query,将会找到所有的注意到,有关带有标签的"一"和"两个"?

有帮助吗?

解决方案

要获得的具有的两个标签 '一' 和 '二' 的注释的细节:

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

当然,替换你的实际列名,希望我的餐桌的假设是正确的。

和实际上有一点可能含糊不清你的问题由于英语以及如何词“和”有时使用。如果你的意思是你想看到的,例如,一记标记“一”,但不是“二”,这应该工作(解释你的“和”的意思,“给我所有标签的笔记‘一’和/加上所有注释标签为“两化”)。不过,如果你只是想有两个标签,票据,这将是去了解的一种方式:

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

编辑:感谢您的建议大家,在我的大脑周一齿轮是有点慢......貌似我应该已经wiki'd它

这样的事情...(你需要另一个链接表)

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

修改:所述NoteLabel表将有两列,noteId和labelId,与复合PK

假设你已经标准化数据库,你应该有另一种表在之间 noteslabels

你应该再用一个 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,标签: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