Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL如何搜索多对多关系_Sql_Search_Many To Many_Relational Division - Fatal编程技术网

SQL如何搜索多对多关系

SQL如何搜索多对多关系,sql,search,many-to-many,relational-division,Sql,Search,Many To Many,Relational Division,我有一个数据库,其中有两个主表notes和label。它们之间存在多对多关系(类似于stackoverflow.com对标签的疑问)。我想知道的是,如何使用SQL使用多个标签搜索注释 例如,如果我有一个带有三个标签“1”、“2”和“3”的注释“test”,还有一个带有标签“1”和“2”的注释“test2”,那么将查找与标签“1”和“2”关联的所有注释的SQL查询是什么 当然,用实际的列名替换,希望我对表的假设是正确的 事实上,由于英语和“And”这个词有时的用法,你的问题中可能会有一些歧义。例如

我有一个数据库,其中有两个主表
notes
label
。它们之间存在多对多关系(类似于stackoverflow.com对标签的疑问)。我想知道的是,如何使用SQL使用多个标签搜索注释

例如,如果我有一个带有三个标签“1”、“2”和“3”的注释“test”,还有一个带有标签“1”和“2”的注释“test2”,那么将查找与标签“1”和“2”关联的所有注释的SQL查询是什么

当然,用实际的列名替换,希望我对表的假设是正确的

事实上,由于英语和“And”这个词有时的用法,你的问题中可能会有一些歧义。例如,如果您的意思是希望看到标记为“一”而不是“二”的便笺,这应该可以(将您的“和”解释为“向我显示所有标签为“一”的便笺和/或所有标签为“二”的便笺”)。但是,如果您只希望便笺同时具有两个标签,这将是一种方法:

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')
编辑:谢谢大家的建议,我脑子里的星期一齿轮有点慢…看起来我应该把它放到维基上

像这样的。。。(您需要另一个链接表)


编辑:NoteLabel表将有两列,noteId和labelId,带有一个复合主键。

假设您有一个规范化的数据库,那么在
注释
标签

然后应该使用
内部联接
将表联接在一起

  • 标签
    表与绑定表(多对多表)连接起来
  • notes
    表与上一个查询连接起来
  • 例如:

    select*from((标签l内部连接标签\u注释ln on l.labelid=ln.labelid)
    ln.notesid=n.noteid)上的内部联接注释n)

    这样,您就将两个表连接在一起了


    现在,您需要添加的是
    where
    子句……但我将把这个问题留给您。

    您没有说这个多对多关系是如何实现的。我假设labels表有is标签(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);
    

    替换为列名,并为标签插入适当的占位符。

    要获取同时具有标签“一”和“二”的注释的详细信息,请执行以下操作:

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

    如果您只需要一个列表,可以使用
    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
    

    注意:我还没有实际测试过这个。它还假设您有一个名为notes\u 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列作为复合主键。

    请给出表布局是否仅尝试动态选择多个注释上使用的标签?如果是这样,我想你需要have关键字。请在问题中明确你是否感兴趣:*所有与标签“一”或“二”(或两者)相关的注释,或*仅与标签“一”和“二”相关的注释。括号都是多余的,但如果您正在构造类似的查询,则可能会很有用。此条件永远不会为真:(mm.labeltext='one'和mm.labeltext='two')(mm.labeltext='one'或mm.labeltext='two')order:mm.labeltext IN('one','two')IN('one','two')IN('one','two'))更好的语法。为什么不把代码放到代码块中,这样它就变得可读了呢?谢谢!到目前为止,唯一能给出正确结果的解决方案!“…SQL查询,它将查找与标签‘一’和‘二’关联的所有注释?”啊,你知道了。我现在有另一种语法,但我直到现在才看到你的+1.
    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;