Cercare più tabelle in SQL
-
19-09-2019 - |
Domanda
Sto cercando di cercare più tavoli contemporaneamente per un termine di ricerca. La mia domanda è:
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
//...
Ma i risultati non sono quelli previsti. Ho circa 50 elementi della categoria "battente", ma quando termine == "Casement" solo voci che hanno "Casement" nella loro item.Description saranno restituiti.
Sto facendo qualcosa di sbagliato? Dovrei fare questo un modo migliore?
Soluzione
Questo è un buon esempio 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 + '%'
CTE sono supportati in SQL Server 2005 +.
Altri suggerimenti
Il suo abbastanza per scrivere
item.Description LIKE '%' + @term + '%'
anziché
item.Description LIKE '%' + @term + '%'
OR
item.Description LIKE '%' + @term
OR
item.Description LIKE @term + '%'
OR
item.Description = @term
Concettualmente vorrei fare cose semplici e quindi modificare da lì, se necessario, per le prestazioni. In primo luogo vorrei creare una vista e poi fare la select fuori di questo.
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 '%'+@term +'%'
GO
Se avete sql2005 e volete testare questo concetto è possibile eseguire il seguente:
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%'
Prova questo:
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
Rendetevi conto che questo causerà un tavolo scansione completa di tutti e quattro i tavoli, così sarà lento se queste tabelle sono di grandi dimensioni. Ma dato quello che si sta cercando di fare, l'unica alternativa sarebbe quella di implementare gli indici full-text sul database ...
Inoltre, se è possiblke che una di queste tabelle non contiene una riga corrispondente per yr condizione di join, si dovrebbe fare tutto il join outer join, e utilizzare IsNull()
su tutti i riferimenti di colonna ...
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