Sql Server – Identifiant exact ou plus

J'ai un tableau "messages" avec des colonnes: "id" , "title" ,

table "categories" avec colonnes: "id" , "title" ,

et "messages_categories" lien table avec des colonnes: "message_id" , "category_id" .

laisse supposer que nous avons des messages avec des ID de

 1,2,3 

et categories avec des ID de

 1,2,3 

messages_categories avec des données de

 message: 1, category: 1 message: 2, category: 1 message: 2, category: 2 message: 3, category: 1 message: 3, category: 2 message: 3, category: 3 

Je veux find le match exact ou plus par exemple

si je search la catégorie 1, je vais recevoir des messages 1,2,3

si je search la catégorie 1,2, je vais recevoir des messages 2,3

si je search pour la catégorie 1,2,3 je vais get seulement le message 3

J'utilise beaucoup d'ids donc joindre pour chaque catégorie peut être trop.

J'ai compris que je peux utiliser "having" déclaration avec "sum" et "count" pour find les lignes exactes mais ce n'est pas assez bon.

Appréciez toute aide, Nevo.

Si vous avez besoin de «plus», utilisez NOT EXISTS, ce qu'on appelle la division relationnelle avec callback .

 SELECT DISTINCT messages_id FROM messages_categories r1 WHERE NOT EXISTS (SELECT * FROM (SELECT 1 as cat_id UNION SELECT 2 ) S -- id of categories needed WHERE NOT EXISTS (SELECT * FROM messages_categories AS r2 WHERE (r1.messages_id = r2.messages_id) AND (r2.category_id = S.cat_id))); 

C'est une division relationnelle .

1) Une solution consiste à utiliser PIVOT:

 DECLARE @filter_cat_id TABLE (cat_id INT NOT NULL PRIMARY KEY); INSERT @filter_cat_id VALUES (1), (2); DECLARE @SqlStatement NVARCHAR(MAX), @PivotColumns NVARCHAR(MAX) = N'', @PivotFilters NVARCHAR(MAX) = N''; SELECT @PivotColumns = @PivotColumns + N', ' + QUOTENAME(f.cat_id), @PivotFilters = @PivotFilters + N'AND z.' + QUOTENAME(f.cat_id) + N' > 0 ' FROM @filter_cat_id f; SELECT @PivotColumns = STUFF(@PivotColumns, 1, 2, N''), @PivotFilters = STUFF(@PivotFilters, 1, 4, N''); --PRINT @PivotColumns --PRINT @PivotFilters SET @SqlStatement = N' SELECT * FROM ( SELECT x.msg_id, x.cat_id FROM (VALUES (1, 1), (2, 1), (2, 2), (3, 1), (3, 2), (3, 3) ) x(msg_id, cat_id) ) y PIVOT (COUNT(y.cat_id) FOR y.cat_id IN (' + @PivotColumns + ') ) z WHERE ' + @PivotFilters EXEC sp_executesql @SqlStatement 

Par exemple, la solution ci-dessus génère la requête [finale] suivante:

 SELECT * FROM ( SELECT x.msg_id, x.cat_id FROM (VALUES (1, 1), (2, 1), (2, 2), (3, 1), (3, 2), (3, 3) ) x(msg_id, cat_id) ) y PIVOT (COUNT(y.cat_id) FOR y.cat_id IN ([1], [2]) ) z WHERE z.[1] > 0 AND z.[2] > 0 

2) Une autre solution utilise GROUP BY et HAVING ainsi:

 DECLARE @filter_cat_id TABLE (cat_id INT NOT NULL PRIMARY KEY); INSERT @filter_cat_id VALUES (1), (2); SELECT x.msg_id FROM (VALUES (1, 1), (2, 1), (2, 2), (3, 1), (3, 2), (3, 3) ) x(msg_id, cat_id) -- Source table INNER JOIN @filter_cat_id f ON x.cat_id = f.cat_id GROUP BY x.msg_id HAVING COUNT(x.cat_id) = (SELECT COUNT(t.cat_id) FROM @filter_cat_id t) -- If there is not UNIQUE index/constraint on source table (msg_id + cat_id) then use COUNT(DISTINCT x.cat_id) -- If filter_cat (cat_id) isn't unique then use COUNT(DISTINCT t.cat_id) 

Quelque chose dans le sens de ceci pourrait fonctionner:

 SELECT DISTINCT x.message_id FROM ( **query-that-gives-the-exact-rows-but-isnt-good-enough** ) AS x