简体   繁体   中英

Querying a Many-to-Many Linking Table

I have a linking table for a many-to-many relationship, with the fields -

  • idNote
  • idTag

I would like to filter for all the tags that are associated with the notes that contain a specified number of tags.

For example, if I select the tags ' Running ', ' Form ', and ' Times ', I would then like to see all the tags that are associated with the notes that have these 3 tags.

This process will be used by the user on the front end to refine the results they are looking for, so I need to be able to generate this SQL with code ( node.js ), with the filtering by tags potentially occurring many times over.

I have the below SQL code, which can query for two tags, but there are some problems with it:

  1. It does not seem efficient
  2. It can not be easily generated through code if another layer of filers needs to be added
SELECT DISTINCT idtag FROM table WHERE idnote IN (SELECT idnote FROM 
(SELECT * FROM table WHERE idnote IN (SELECT idnote FROM table WHERE idtag 
= 'Example')) as t1 where t1.idtag = 'SecondExample');

I am hoping for some suggestions on how to improve the efficiency of this code, as well as turning the sql statement into something that is easily code generateable.

Sounds like a data trap, the Cartesian product https://en.wikipedia.org/wiki/Cartesian_product

Is there anything to bridge the two tables? Like a common table between the two that we can join to? Instead of N:N
Table A would be something in common with the notes table (B) and tags table (C) we could have Table A join to Table B as 1:N and Table A also join to C as 1:N

Then you could stitch the two separate facts together with a common table

Try something like this:

; with cteTagList as 
    (select 'Example' idtag
    union select 'SecondExample'
    --...
    union select 'LastExample'
    )
select t.idnote
from table t inner join cteTabList l on l.idtag = t.idtag
group by t.idnote
having count(*) = [NUMBER_OF_SEARCH_TAGS]

Where you generate a CTE (Common Table Expression) which contains all the search tags. Join it with the many-to-many relation table, and only select those notes that hat count equal to the number of search tags inputed by the user, noted [NUMBER_OF_SEARCH_TAGS] in the query

I used your example of 'Running','Form','Times' as the specified set of tags.

select distinct idTag from table 
where idNote in (select idNote from table where idTag in ('Running'))
and idNote in (select idNote from table where idTag in ('Form'))
and idNote in (select idNote from table where idTag in ('Times'))


The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM