2009-11-11 7 views
0

J'essaie de rechercher plusieurs tables à la fois pour un terme de recherche. Ma requête est:RECHERCHE plusieurs tables dans SQL

SELECT item.ItemID 
    FROM Inventory.Item item 
     JOIN Inventory.Category catR // each item can be in several categories 
      ON catR.ItemID = item.ItemID 
     JOIN Category.Category cat 
      ON cat.CategoryID = catR.CategoryID 
     JOIN Inventory.Brand bran 
      ON bran.BrandID = item.BrandID 
    WHERE 
     item.Description LIKE '%' + @term + '%' 
     OR 
     item.Description LIKE '%' + @term 
     OR 
     item.Description LIKE @term + '%' 
     OR 
     item.Description = @term 
     OR 
     cat.CategoryName LIKE '%' + @term + '%' 
      //same pattern as item.Description used to search CategoryName 
      //... 
     OR 
     bran.BrandName LIKE '%' + @term + '%' 
      //same pattern as item.Description used to search BrandName 
      //... 

Mais les résultats ne sont pas comme prévu. J'ai environ 50 articles dans la catégorie "Casement", mais quand terme == "Casement" seuls les articles qui ont "Casement" dans leur article.Description sera retourné.

Est-ce que je fais quelque chose de mal? Devrais-je faire cela d'une meilleure façon?

+0

Essayez 'LEFT JOIN's. Tout inventaire qui manque d'une marque ("BrandID" est NULL ou est désintégré de manière référentielle) serait exclu par votre SQL, quel que soit son "Nom de Catégorie". – pilcrow

Répondre

1

Ceci est un bon exemple CTE:

WITH items AS (
    SELECT i.itemid, 
      i.description, 
      cat.category_name, 
      b.brandname 
     FROM INVENTORY.ITEM i 
    LEFT JOIN INVENTORY.CATEGORY c ON c.itemid = i.itemid 
    LEFT JOIN CATEGORY.CATEGORY cat ON cat.CategoryID = c.categoryid 
    LEFT JOIN INVENTORY.BRAND b ON b.brandid = i.brandid) 
SELECT a.itemid 
    FROM items a 
WHERE a.description LIKE '%' + @term + '%' 
UNION ALL 
SELECT b.itemid 
    FROM items b 
WHERE b.categoryname LIKE '%' + @term + '%' 
UNION ALL 
SELECT c.itemid 
    FROM items c 
WHERE c.brandname LIKE '%' + @term + '%' 

CTEs sont pris en charge dans SQL Server 2005+.

+0

Cela a fonctionné très bien. Merci! –

2

Son assez pour écrire

item.Description LIKE '%' + @term + '%' 

au lieu de

item.Description LIKE '%' + @term + '%' 
OR 
    item.Description LIKE '%' + @term 
OR 
    item.Description LIKE @term + '%' 
OR 
    item.Description = @term 
0

Essayez ceci:

Select i.ItemID  
From Inventory.Item i 
    Join Inventory.Category ic 
    On ic.ItemID = i.ItemID   
    Join Category.Category cc    
    On cat.CategoryID = ic.CategoryID   
    Join Inventory.Brand ib 
    On ib.BrandID = i.BrandID 
Where CharIndex(@Term, 
     i.Description + '|' + 
    ic.Description + '|' + 
    cc.Description + '|' + 
    ib.Description) > 0 

Sachez que cela provoquera une analyse complète de la table des quatre tables, il sera lent si ces tables sont grandes. Mais étant donné ce que vous essayez de faire, la seule alternative serait d'implémenter des index de texte intégral sur la base de données ...

De même, s'il est possible que l'une de ces tables ne contienne pas de ligne correspondante pour yr les conditions de jointure , vous devez faire toutes les jointures les jointures externes, et utiliser IsNull() sur toutes les références de colonne ...

Select i.ItemID  
From Inventory.Item i 
    Left Join Inventory.Category ic 
    On ic.ItemID = i.ItemID   
    Left Join Category.Category cc    
    On cat.CategoryID = ic.CategoryID   
    Left Join Inventory.Brand ib 
    On ib.BrandID = i.BrandID 
Where CharIndex(@Term, 
     i.Description + '|' + 
    IsNull(ic.Description, '') + '|' + 
    IsNull(cc.Description, '') + '|' + 
    IsNull(ib.Description, '')) > 0 
+0

Pour une raison quelconque, tous les enregistrements de la base de données ont été sélectionnés. –

+0

Quelle valeur pour @Term avez-vous reçu? Si vous passez une valeur qui est dans le champ Description de chaque enregistrement, alors il retournera chaque enregistrement, sinon vous faites quelque chose d'autre dans votre requête qui est 'incluant tous les enregistrements ... et Oh, j'ai eu une virgule supplémentaire là, ça aurait dû faire que le SQL lance une erreur de syntaxe, il est maintenant supprimé ... –

2

Conceptuellement je garderais simple puis changer à partir de là si nécessaire pour la performance. D'abord, je voudrais créer une vue, puis faire le choix de cela.

CREATE VIEW vSearchTables 
AS 

SELECT item.ItemID, 'Item' AS TableName, item.Descripton AS Txt 
FROM Inventory.Item item 

UNION ALL 

SELECT catR.ItemID, 'Category' AS TableName, cat.CategoryName AS Txt 
FROM Inventory.Category catR 
JOIN Category.Category cat 
ON cat.CategoryID = catR.CategoryID 

UNION ALL 

SELECT item.ItemID, 'Brand' AS TableName, bran.BrandName AS Txt 
FROM Inventory.Item item 
JOIN Inventory.Brand bran 
ON bran.BrandID = item.BrandID 

GO 



SELECT ItemID 
FROM vSearchTables 
WHERE Txt LIKE '%'[email protected] +'%' 


GO 

Si vous avez sql2005 et que vous voulez tester ce concept, vous pouvez exécuter les éléments suivants:

CREATE VIEW vSearchTables 
AS 

select object_name(o.object_id) Object, o.type, m.definition as Txt 
from sys.sql_modules m  
join sys.objects o on m.object_id = o.object_id  

GO 


SELECT * 
FROM vSearchTables 
WHERE Txt LIKE '%TRIGGER%' 
+0

Merci, je vais essayer le matin et vous le faire savoir. –

+0

Je vais encore essayer ça ... je n'ai pas eu le temps. –

+0

J'ai une erreur: "Syntaxe incorrecte près de 'VIEW'" –

Questions connexes