ПОИСК нескольких таблиц в SQL - PullRequest
0 голосов
/ 11 ноября 2009

Я пытаюсь выполнить поиск по нескольким таблицам одновременно. Мой запрос:

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
             //...

Но результаты не такие, как ожидалось. У меня есть около 50 наименований в категории «створки», но когда термин == «створки», только предметы, которые имеют «створки» в своем предмете. Описание будет возвращено.

Я что-то не так делаю? Должен ли я сделать это лучше?

Ответы [ 4 ]

2 голосов
/ 12 ноября 2009

Концептуально я хотел бы сохранить это простым, а затем изменить его оттуда, если это необходимо для производительности. Сначала я создал бы представление, а затем сделал бы выбор из этого.

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

Если у вас есть sql2005 и вы хотите проверить эту концепцию, вы можете выполнить следующее:

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%' 
2 голосов
/ 11 ноября 2009

Достаточно написать

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

вместо

item.Description LIKE '%' + @term + '%'
OR
   item.Description LIKE '%' + @term
OR
   item.Description LIKE @term + '%'
OR
   item.Description = @term
1 голос
/ 12 ноября 2009

Это хороший пример 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 поддерживаются в SQL Server 2005+.

0 голосов
/ 11 ноября 2009

Попробуйте это:

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

Поймите, что это приведет к полному сканированию всех четырех таблиц, поэтому, если эти таблицы будут большими, будет медленно. Но, учитывая то, что вы пытаетесь сделать, единственной альтернативой будет внедрение полнотекстовых индексов в базу данных ...

Кроме того, если возможно, что в одной из этих таблиц нет подходящей строки для условия соединения yr, необходимо выполнить все внешние соединения объединений и использовать IsNull() для всех ссылок на столбцы ...

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
...