Many-To-Many select only rows with exactly same tags










1















I have 3 tables: tags, products and relation table between them.
Relation table looks for example like this:



tagId | ProductId
1 | 1
2 | 1
2 | 9


The user can pick two options "All of these" or "One of these".



So if user picks All of these, it's means that the product must have exactly all of tags which the user chose.



So if user pick tags with id 1 and 2, it should select only product with id 1, because this product has exactly the same tags the user chose. (Another way is if the user picks the tag with id 2, it should select only product with id 9.)



So, the product has to have all tags which the user chose (no more, no less).



SQL that I already have for Any/One of these:



SELECT DISTINCT s.SKU 
FROM SKUToEAN as s
LEFT JOIN ProductDetails as p ON s.ProductDetailID=p.id
JOIN ProductTagRelation as ptr ON (ptr.productId=p.id and ptr.tagId IN(Ids of selected tags))


Example behavior:



TagId = 1 it should select => None
TagId = 2 it should select => 9
TagId = 1,2 it should select = 1,9


So probably I need two queries. One for any/one of these ( I already have this one ) and the second for all of these.
With PHP I decide which query to use.










share|improve this question



















  • 2





    You said "not more, not less". When you search for 1,2, expected result is not 1? 9 only has tag 2 (missing tag 1).

    – DanB
    Nov 15 '18 at 20:07















1















I have 3 tables: tags, products and relation table between them.
Relation table looks for example like this:



tagId | ProductId
1 | 1
2 | 1
2 | 9


The user can pick two options "All of these" or "One of these".



So if user picks All of these, it's means that the product must have exactly all of tags which the user chose.



So if user pick tags with id 1 and 2, it should select only product with id 1, because this product has exactly the same tags the user chose. (Another way is if the user picks the tag with id 2, it should select only product with id 9.)



So, the product has to have all tags which the user chose (no more, no less).



SQL that I already have for Any/One of these:



SELECT DISTINCT s.SKU 
FROM SKUToEAN as s
LEFT JOIN ProductDetails as p ON s.ProductDetailID=p.id
JOIN ProductTagRelation as ptr ON (ptr.productId=p.id and ptr.tagId IN(Ids of selected tags))


Example behavior:



TagId = 1 it should select => None
TagId = 2 it should select => 9
TagId = 1,2 it should select = 1,9


So probably I need two queries. One for any/one of these ( I already have this one ) and the second for all of these.
With PHP I decide which query to use.










share|improve this question



















  • 2





    You said "not more, not less". When you search for 1,2, expected result is not 1? 9 only has tag 2 (missing tag 1).

    – DanB
    Nov 15 '18 at 20:07













1












1








1








I have 3 tables: tags, products and relation table between them.
Relation table looks for example like this:



tagId | ProductId
1 | 1
2 | 1
2 | 9


The user can pick two options "All of these" or "One of these".



So if user picks All of these, it's means that the product must have exactly all of tags which the user chose.



So if user pick tags with id 1 and 2, it should select only product with id 1, because this product has exactly the same tags the user chose. (Another way is if the user picks the tag with id 2, it should select only product with id 9.)



So, the product has to have all tags which the user chose (no more, no less).



SQL that I already have for Any/One of these:



SELECT DISTINCT s.SKU 
FROM SKUToEAN as s
LEFT JOIN ProductDetails as p ON s.ProductDetailID=p.id
JOIN ProductTagRelation as ptr ON (ptr.productId=p.id and ptr.tagId IN(Ids of selected tags))


Example behavior:



TagId = 1 it should select => None
TagId = 2 it should select => 9
TagId = 1,2 it should select = 1,9


So probably I need two queries. One for any/one of these ( I already have this one ) and the second for all of these.
With PHP I decide which query to use.










share|improve this question
















I have 3 tables: tags, products and relation table between them.
Relation table looks for example like this:



tagId | ProductId
1 | 1
2 | 1
2 | 9


The user can pick two options "All of these" or "One of these".



So if user picks All of these, it's means that the product must have exactly all of tags which the user chose.



So if user pick tags with id 1 and 2, it should select only product with id 1, because this product has exactly the same tags the user chose. (Another way is if the user picks the tag with id 2, it should select only product with id 9.)



So, the product has to have all tags which the user chose (no more, no less).



SQL that I already have for Any/One of these:



SELECT DISTINCT s.SKU 
FROM SKUToEAN as s
LEFT JOIN ProductDetails as p ON s.ProductDetailID=p.id
JOIN ProductTagRelation as ptr ON (ptr.productId=p.id and ptr.tagId IN(Ids of selected tags))


Example behavior:



TagId = 1 it should select => None
TagId = 2 it should select => 9
TagId = 1,2 it should select = 1,9


So probably I need two queries. One for any/one of these ( I already have this one ) and the second for all of these.
With PHP I decide which query to use.







mysql many-to-many






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 6:29









BSMP

2,62952536




2,62952536










asked Nov 15 '18 at 19:15









Frederik FakoFrederik Fako

83




83







  • 2





    You said "not more, not less". When you search for 1,2, expected result is not 1? 9 only has tag 2 (missing tag 1).

    – DanB
    Nov 15 '18 at 20:07












  • 2





    You said "not more, not less". When you search for 1,2, expected result is not 1? 9 only has tag 2 (missing tag 1).

    – DanB
    Nov 15 '18 at 20:07







2




2





You said "not more, not less". When you search for 1,2, expected result is not 1? 9 only has tag 2 (missing tag 1).

– DanB
Nov 15 '18 at 20:07





You said "not more, not less". When you search for 1,2, expected result is not 1? 9 only has tag 2 (missing tag 1).

– DanB
Nov 15 '18 at 20:07












2 Answers
2






active

oldest

votes


















0














You can GROUP BY on the ProductID and use conditional aggregation based filtering inside the Having clause. MySQL automatically casts boolean values to 0/1 when using in numeric context. So, in order to have a specific tagID value available against a ProductID, its SUM(tagId = ..) should be 1.



All of these:



SELECT ptr.productId, s.SKU 
FROM SKUToEAN AS s
LEFT JOIN ProductDetails AS p
ON p.id = s.ProductDetailID
JOIN ProductTagRelation AS ptr
ON ptr.productId = p.id
GROUP BY ptr.productId, s.SKU
HAVING SUM(ptr.tagID = 1) AND -- 1 should be there
SUM(ptr.tagID = 2) AND -- 2 should be there
NOT SUM(ptr.tagID NOT IN (1,2)) -- other than 1,2 should not be there





share|improve this answer

























  • @FrederikFako please edit the question and add this there. I will modify my answer accordingly.

    – Madhur Bhaiya
    Nov 15 '18 at 19:45











  • I edited my question can you look at it now?

    – Frederik Fako
    Nov 15 '18 at 19:57












  • @FrederikFako please note that queries will be different for the two cases.

    – Madhur Bhaiya
    Nov 15 '18 at 20:02











  • Im using PHP if clause to decide which querie use. Im sorry for my English, I hope I understood what you mean

    – Frederik Fako
    Nov 15 '18 at 20:06






  • 1





    Jep, i think this is what I need. Thanks you very much!

    – Frederik Fako
    Nov 15 '18 at 20:10


















0














Is this you are looking for (for all condition)?



select product.id
from products
inner join <table> on products.id = <table>.productId
group by product.id
having group_concat(<table>.tagId order by <table>.tagId separator ',') = '1,2';





share|improve this answer

























  • I edited my question can you look at it now? I only want Exaclly All of these. Any/One of these I already has.

    – Frederik Fako
    Nov 15 '18 at 20:03











  • This should do the tricks. If you search 1 and 2, search = '1,2';

    – DanB
    Nov 15 '18 at 20:05










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53326477%2fmany-to-many-select-only-rows-with-exactly-same-tags%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














You can GROUP BY on the ProductID and use conditional aggregation based filtering inside the Having clause. MySQL automatically casts boolean values to 0/1 when using in numeric context. So, in order to have a specific tagID value available against a ProductID, its SUM(tagId = ..) should be 1.



All of these:



SELECT ptr.productId, s.SKU 
FROM SKUToEAN AS s
LEFT JOIN ProductDetails AS p
ON p.id = s.ProductDetailID
JOIN ProductTagRelation AS ptr
ON ptr.productId = p.id
GROUP BY ptr.productId, s.SKU
HAVING SUM(ptr.tagID = 1) AND -- 1 should be there
SUM(ptr.tagID = 2) AND -- 2 should be there
NOT SUM(ptr.tagID NOT IN (1,2)) -- other than 1,2 should not be there





share|improve this answer

























  • @FrederikFako please edit the question and add this there. I will modify my answer accordingly.

    – Madhur Bhaiya
    Nov 15 '18 at 19:45











  • I edited my question can you look at it now?

    – Frederik Fako
    Nov 15 '18 at 19:57












  • @FrederikFako please note that queries will be different for the two cases.

    – Madhur Bhaiya
    Nov 15 '18 at 20:02











  • Im using PHP if clause to decide which querie use. Im sorry for my English, I hope I understood what you mean

    – Frederik Fako
    Nov 15 '18 at 20:06






  • 1





    Jep, i think this is what I need. Thanks you very much!

    – Frederik Fako
    Nov 15 '18 at 20:10















0














You can GROUP BY on the ProductID and use conditional aggregation based filtering inside the Having clause. MySQL automatically casts boolean values to 0/1 when using in numeric context. So, in order to have a specific tagID value available against a ProductID, its SUM(tagId = ..) should be 1.



All of these:



SELECT ptr.productId, s.SKU 
FROM SKUToEAN AS s
LEFT JOIN ProductDetails AS p
ON p.id = s.ProductDetailID
JOIN ProductTagRelation AS ptr
ON ptr.productId = p.id
GROUP BY ptr.productId, s.SKU
HAVING SUM(ptr.tagID = 1) AND -- 1 should be there
SUM(ptr.tagID = 2) AND -- 2 should be there
NOT SUM(ptr.tagID NOT IN (1,2)) -- other than 1,2 should not be there





share|improve this answer

























  • @FrederikFako please edit the question and add this there. I will modify my answer accordingly.

    – Madhur Bhaiya
    Nov 15 '18 at 19:45











  • I edited my question can you look at it now?

    – Frederik Fako
    Nov 15 '18 at 19:57












  • @FrederikFako please note that queries will be different for the two cases.

    – Madhur Bhaiya
    Nov 15 '18 at 20:02











  • Im using PHP if clause to decide which querie use. Im sorry for my English, I hope I understood what you mean

    – Frederik Fako
    Nov 15 '18 at 20:06






  • 1





    Jep, i think this is what I need. Thanks you very much!

    – Frederik Fako
    Nov 15 '18 at 20:10













0












0








0







You can GROUP BY on the ProductID and use conditional aggregation based filtering inside the Having clause. MySQL automatically casts boolean values to 0/1 when using in numeric context. So, in order to have a specific tagID value available against a ProductID, its SUM(tagId = ..) should be 1.



All of these:



SELECT ptr.productId, s.SKU 
FROM SKUToEAN AS s
LEFT JOIN ProductDetails AS p
ON p.id = s.ProductDetailID
JOIN ProductTagRelation AS ptr
ON ptr.productId = p.id
GROUP BY ptr.productId, s.SKU
HAVING SUM(ptr.tagID = 1) AND -- 1 should be there
SUM(ptr.tagID = 2) AND -- 2 should be there
NOT SUM(ptr.tagID NOT IN (1,2)) -- other than 1,2 should not be there





share|improve this answer















You can GROUP BY on the ProductID and use conditional aggregation based filtering inside the Having clause. MySQL automatically casts boolean values to 0/1 when using in numeric context. So, in order to have a specific tagID value available against a ProductID, its SUM(tagId = ..) should be 1.



All of these:



SELECT ptr.productId, s.SKU 
FROM SKUToEAN AS s
LEFT JOIN ProductDetails AS p
ON p.id = s.ProductDetailID
JOIN ProductTagRelation AS ptr
ON ptr.productId = p.id
GROUP BY ptr.productId, s.SKU
HAVING SUM(ptr.tagID = 1) AND -- 1 should be there
SUM(ptr.tagID = 2) AND -- 2 should be there
NOT SUM(ptr.tagID NOT IN (1,2)) -- other than 1,2 should not be there






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 15 '18 at 20:04

























answered Nov 15 '18 at 19:19









Madhur BhaiyaMadhur Bhaiya

19.6k62236




19.6k62236












  • @FrederikFako please edit the question and add this there. I will modify my answer accordingly.

    – Madhur Bhaiya
    Nov 15 '18 at 19:45











  • I edited my question can you look at it now?

    – Frederik Fako
    Nov 15 '18 at 19:57












  • @FrederikFako please note that queries will be different for the two cases.

    – Madhur Bhaiya
    Nov 15 '18 at 20:02











  • Im using PHP if clause to decide which querie use. Im sorry for my English, I hope I understood what you mean

    – Frederik Fako
    Nov 15 '18 at 20:06






  • 1





    Jep, i think this is what I need. Thanks you very much!

    – Frederik Fako
    Nov 15 '18 at 20:10

















  • @FrederikFako please edit the question and add this there. I will modify my answer accordingly.

    – Madhur Bhaiya
    Nov 15 '18 at 19:45











  • I edited my question can you look at it now?

    – Frederik Fako
    Nov 15 '18 at 19:57












  • @FrederikFako please note that queries will be different for the two cases.

    – Madhur Bhaiya
    Nov 15 '18 at 20:02











  • Im using PHP if clause to decide which querie use. Im sorry for my English, I hope I understood what you mean

    – Frederik Fako
    Nov 15 '18 at 20:06






  • 1





    Jep, i think this is what I need. Thanks you very much!

    – Frederik Fako
    Nov 15 '18 at 20:10
















@FrederikFako please edit the question and add this there. I will modify my answer accordingly.

– Madhur Bhaiya
Nov 15 '18 at 19:45





@FrederikFako please edit the question and add this there. I will modify my answer accordingly.

– Madhur Bhaiya
Nov 15 '18 at 19:45













I edited my question can you look at it now?

– Frederik Fako
Nov 15 '18 at 19:57






I edited my question can you look at it now?

– Frederik Fako
Nov 15 '18 at 19:57














@FrederikFako please note that queries will be different for the two cases.

– Madhur Bhaiya
Nov 15 '18 at 20:02





@FrederikFako please note that queries will be different for the two cases.

– Madhur Bhaiya
Nov 15 '18 at 20:02













Im using PHP if clause to decide which querie use. Im sorry for my English, I hope I understood what you mean

– Frederik Fako
Nov 15 '18 at 20:06





Im using PHP if clause to decide which querie use. Im sorry for my English, I hope I understood what you mean

– Frederik Fako
Nov 15 '18 at 20:06




1




1





Jep, i think this is what I need. Thanks you very much!

– Frederik Fako
Nov 15 '18 at 20:10





Jep, i think this is what I need. Thanks you very much!

– Frederik Fako
Nov 15 '18 at 20:10













0














Is this you are looking for (for all condition)?



select product.id
from products
inner join <table> on products.id = <table>.productId
group by product.id
having group_concat(<table>.tagId order by <table>.tagId separator ',') = '1,2';





share|improve this answer

























  • I edited my question can you look at it now? I only want Exaclly All of these. Any/One of these I already has.

    – Frederik Fako
    Nov 15 '18 at 20:03











  • This should do the tricks. If you search 1 and 2, search = '1,2';

    – DanB
    Nov 15 '18 at 20:05















0














Is this you are looking for (for all condition)?



select product.id
from products
inner join <table> on products.id = <table>.productId
group by product.id
having group_concat(<table>.tagId order by <table>.tagId separator ',') = '1,2';





share|improve this answer

























  • I edited my question can you look at it now? I only want Exaclly All of these. Any/One of these I already has.

    – Frederik Fako
    Nov 15 '18 at 20:03











  • This should do the tricks. If you search 1 and 2, search = '1,2';

    – DanB
    Nov 15 '18 at 20:05













0












0








0







Is this you are looking for (for all condition)?



select product.id
from products
inner join <table> on products.id = <table>.productId
group by product.id
having group_concat(<table>.tagId order by <table>.tagId separator ',') = '1,2';





share|improve this answer















Is this you are looking for (for all condition)?



select product.id
from products
inner join <table> on products.id = <table>.productId
group by product.id
having group_concat(<table>.tagId order by <table>.tagId separator ',') = '1,2';






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 15 '18 at 20:05

























answered Nov 15 '18 at 19:21









DanBDanB

1,7521315




1,7521315












  • I edited my question can you look at it now? I only want Exaclly All of these. Any/One of these I already has.

    – Frederik Fako
    Nov 15 '18 at 20:03











  • This should do the tricks. If you search 1 and 2, search = '1,2';

    – DanB
    Nov 15 '18 at 20:05

















  • I edited my question can you look at it now? I only want Exaclly All of these. Any/One of these I already has.

    – Frederik Fako
    Nov 15 '18 at 20:03











  • This should do the tricks. If you search 1 and 2, search = '1,2';

    – DanB
    Nov 15 '18 at 20:05
















I edited my question can you look at it now? I only want Exaclly All of these. Any/One of these I already has.

– Frederik Fako
Nov 15 '18 at 20:03





I edited my question can you look at it now? I only want Exaclly All of these. Any/One of these I already has.

– Frederik Fako
Nov 15 '18 at 20:03













This should do the tricks. If you search 1 and 2, search = '1,2';

– DanB
Nov 15 '18 at 20:05





This should do the tricks. If you search 1 and 2, search = '1,2';

– DanB
Nov 15 '18 at 20:05

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53326477%2fmany-to-many-select-only-rows-with-exactly-same-tags%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Barbados

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3