English 中文(简体)
SEARCH several Tables IN SQL
原标题:

I m trying to search several tables at once for a search term. My query is:

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

But the results are not as expected. I have about 50 items in the category "Casement" but when term == "Casement" only items that have "Casement" in their item.Description will be returned.

Am I doing something wrong? Should I do this a better way?

最佳回答

This is a good CTE example:

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 are supported in SQL Server 2005+.

问题回答

Its enough to write

item.Description LIKE  %  + @term +  % 

instead of

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

Conceptually I would keep it simple and then change it from there if needed for performance. First I would create a view and then do the select off of that.

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

If you have sql2005 and want to test this concept you can run the following:

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%  

Try this:

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

Realize that this will cause a full table scan of all four tables, so it will be slow if these tables are large. But given what you are trying to do, the only alternative would be to implement full text indices on the database...

Also, if it is possiblke that one of these tables does not contain a matching row for yr join condition, you should make all the joins outer joins, and use IsNull() on all the column references...

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




相关问题
SQL SubQuery getting particular column

I noticed that there were some threads with similar questions, and I did look through them but did not really get a convincing answer. Here s my question: The subquery below returns a Table with 3 ...

难以执行 REGEXP_SUBSTR

I m 查询Oracle 10g。 我有两张表格(样本数据见下文)。 i m 试图提取一些领域

SQL Query Shortcuts

What are some cool SQL shorthands that you know of? For example, something I learned today is you can specify to group by an index: SELECT col1, col2 FROM table GROUP BY 2 This will group by col2

PHP array callback functions for cleaning output

I have an array of output from a database. I am wondering what the cleanest way to filter the values is example array Array ( [0] => Array ( [title] => title 1 ...

OracleParameter and DBNull.Value

we have a table in an Oracle Database which contains a column with the type Char(3 Byte). Now we use a parameterized sql to select some rows with a DBNull.Value and it doesn t work: OracleCommand ...

Running numbers in SQL

I have a SQL-statement like this: SELECT name FROM users WHERE deleted = 0; How can i create a result set with a running number in the first row? So the result would look like this: 1 Name_1 2 ...

How to get SQL queries for each user where env is production

I’m developing an application dedicated to generate statistical reports, I would like that user after saving their stat report they save sql queries too. To do that I wrote the following module: ...

热门标签