Sql 基于记录的条件的查询

Sql 基于记录的条件的查询,sql,sql-server,Sql,Sql Server,有两张桌子 Categories(Id, Name) Products(Id, Text, CategoryId) 或 我们不想使用动态查询 谢谢您的帮助。根据Giorgos的评论,您需要规范化您的过滤器表。如果您一直坚持这种设计,下面是一个解决方案: 首先,您需要一个字符串拆分器。这里有一张是从亚伦·伯特兰的作品中摘取的: 假设标准化是可能的,下面是一个简单的查询: 创建示例表: DECLARE @Categories as table ( id int identity(1,1),

有两张桌子

Categories(Id, Name) Products(Id, Text, CategoryId) 或

我们不想使用动态查询


谢谢您的帮助。

根据Giorgos的评论,您需要规范化您的
过滤器
表。如果您一直坚持这种设计,下面是一个解决方案:

首先,您需要一个字符串拆分器。这里有一张是从亚伦·伯特兰的作品中摘取的:


假设标准化是可能的,下面是一个简单的查询:

创建示例表:

DECLARE @Categories as table 
(
    id int identity(1,1), 
    name char(1)
)

DECLARE @Products as table 
(
    id int identity(1,1), 
    name varchar(100),
    categoryId int
)

DECLARE @Filter as table 
(
    id int identity(1,1), 
    ContainText varchar(100)
)

DECLARE @FilterCategories as table 
(
    FilterId int, 
    CategoryId int,
    PRIMARY KEY(filterId, CategoryId)
)
INSERT INTO @Categories 
VALUES ('A'),('B'),('C'),('D'),('E')

INSERT INTO @Products (name, categoryId) 
VALUES ('cat A', 1),('category A', 1), ('cat B', 2), ('category B', 2)

INSERT INTO @Filter 
VALUES ('gory'), ('cat')

INSERT INTO @FilterCategories 
VALUES (1, 1), (1, 2), (2, 1)
SELECT  DISTINCT p.id As ProductId, 
        p.name As ProductName,
        c.name As CategoryName
FROM @Filter f
INNER JOIN @FilterCategories fc ON(f.id = fc.FilterId)
INNER JOIN  @Products p ON(p.categoryId = fc.CategoryId)
INNER JOIN @Categories c ON(p.categoryId = c.id)
WHERE p.name LIKE '%'+ f.ContainText +'%'
ProductId   ProductName                    CategoryName
----------- ------------------------------ ------------
1           cat A                          A
2           category A                     A
4           category B                     B
填充示例表:

DECLARE @Categories as table 
(
    id int identity(1,1), 
    name char(1)
)

DECLARE @Products as table 
(
    id int identity(1,1), 
    name varchar(100),
    categoryId int
)

DECLARE @Filter as table 
(
    id int identity(1,1), 
    ContainText varchar(100)
)

DECLARE @FilterCategories as table 
(
    FilterId int, 
    CategoryId int,
    PRIMARY KEY(filterId, CategoryId)
)
INSERT INTO @Categories 
VALUES ('A'),('B'),('C'),('D'),('E')

INSERT INTO @Products (name, categoryId) 
VALUES ('cat A', 1),('category A', 1), ('cat B', 2), ('category B', 2)

INSERT INTO @Filter 
VALUES ('gory'), ('cat')

INSERT INTO @FilterCategories 
VALUES (1, 1), (1, 2), (2, 1)
SELECT  DISTINCT p.id As ProductId, 
        p.name As ProductName,
        c.name As CategoryName
FROM @Filter f
INNER JOIN @FilterCategories fc ON(f.id = fc.FilterId)
INNER JOIN  @Products p ON(p.categoryId = fc.CategoryId)
INNER JOIN @Categories c ON(p.categoryId = c.id)
WHERE p.name LIKE '%'+ f.ContainText +'%'
ProductId   ProductName                    CategoryName
----------- ------------------------------ ------------
1           cat A                          A
2           category A                     A
4           category B                     B
查询:

DECLARE @Categories as table 
(
    id int identity(1,1), 
    name char(1)
)

DECLARE @Products as table 
(
    id int identity(1,1), 
    name varchar(100),
    categoryId int
)

DECLARE @Filter as table 
(
    id int identity(1,1), 
    ContainText varchar(100)
)

DECLARE @FilterCategories as table 
(
    FilterId int, 
    CategoryId int,
    PRIMARY KEY(filterId, CategoryId)
)
INSERT INTO @Categories 
VALUES ('A'),('B'),('C'),('D'),('E')

INSERT INTO @Products (name, categoryId) 
VALUES ('cat A', 1),('category A', 1), ('cat B', 2), ('category B', 2)

INSERT INTO @Filter 
VALUES ('gory'), ('cat')

INSERT INTO @FilterCategories 
VALUES (1, 1), (1, 2), (2, 1)
SELECT  DISTINCT p.id As ProductId, 
        p.name As ProductName,
        c.name As CategoryName
FROM @Filter f
INNER JOIN @FilterCategories fc ON(f.id = fc.FilterId)
INNER JOIN  @Products p ON(p.categoryId = fc.CategoryId)
INNER JOIN @Categories c ON(p.categoryId = c.id)
WHERE p.name LIKE '%'+ f.ContainText +'%'
ProductId   ProductName                    CategoryName
----------- ------------------------------ ------------
1           cat A                          A
2           category A                     A
4           category B                     B
结果:

DECLARE @Categories as table 
(
    id int identity(1,1), 
    name char(1)
)

DECLARE @Products as table 
(
    id int identity(1,1), 
    name varchar(100),
    categoryId int
)

DECLARE @Filter as table 
(
    id int identity(1,1), 
    ContainText varchar(100)
)

DECLARE @FilterCategories as table 
(
    FilterId int, 
    CategoryId int,
    PRIMARY KEY(filterId, CategoryId)
)
INSERT INTO @Categories 
VALUES ('A'),('B'),('C'),('D'),('E')

INSERT INTO @Products (name, categoryId) 
VALUES ('cat A', 1),('category A', 1), ('cat B', 2), ('category B', 2)

INSERT INTO @Filter 
VALUES ('gory'), ('cat')

INSERT INTO @FilterCategories 
VALUES (1, 1), (1, 2), (2, 1)
SELECT  DISTINCT p.id As ProductId, 
        p.name As ProductName,
        c.name As CategoryName
FROM @Filter f
INNER JOIN @FilterCategories fc ON(f.id = fc.FilterId)
INNER JOIN  @Products p ON(p.categoryId = fc.CategoryId)
INNER JOIN @Categories c ON(p.categoryId = c.id)
WHERE p.name LIKE '%'+ f.ContainText +'%'
ProductId   ProductName                    CategoryName
----------- ------------------------------ ------------
1           cat A                          A
2           category A                     A
4           category B                     B

要规范化
过滤器
表,您可以使用如下内容:

DECLARE @xml xml

;WITH Filters AS (
SELECT *
FROM (VALUES
('100,101', 'A'),
('200,201', 'B'),
('300,301,302', 'C')
) as t(CategoryIds, ContainText)
)

SELECT @xml =(
SELECT CAST ('<b>' + ContainText + '<a>'+REPLACE(CategoryIds,',','</a><a>') + '</a></b>' as xml)
FROM Filters
FOR XML PATH('')
)

SELECT  t.v.value('../.','nvarchar(1)') as ContainText,
        t.v.value('.','int') as CategoryId
FROM @xml.nodes('/b/a') as t(v)
然后,您可以将此表连接到
产品
类别

SELECT *
FROM NormFilters nf
INNER JOIN Categories c  -- (Id, Name)
    ON nf.CategoryId = c.Id
INNER JOIN Products p  --(Id, Text, CategoryId)
    ON c.CategoryId = p.CategoryId AND p.[Text] LIKE '%' + nf.ContainText +'%'

您还可以尝试以下不需要规范化的查询。因此,如果您无法更新表,请尝试下面的查询,它是简单的
JOIN

--create table categories(id int, name varchar(100));
--create table products(id int, text varchar(100), categoryid int);
--create table filters(categoryids varchar(100), containtext varchar(10));
--insert into filters values
--('100,101','A'),
--('200,201','B');
--insert into products values 
--(1,'Random',100),
--(2,'rps',101),
--(3,'rps',200),
--(4,'rpsb',201);
--insert into categories values 
--(100,'Cat100'),
--(101,'Cat101'),
--(200,'Cat200'),
--(201,'Cat201');

select 
  P.*,C.Name 
from Products P join Categories C 
      on C.Id=P.CategoryId 
join Filters F 
     on text like '%'+ContainText+'%' 
          and   ','+ CategoryIds +',' like '%,'+cast(C.ID as varchar(100)) +',%'

请发布示例数据和预期结果。您的
过滤器
表需要规范化。像这样存储逗号分隔的值是一个非常糟糕的主意。如果您对规范化筛选表有任何想法,请提示我。我认为它有清晰的数据,有些产品按某些类别。您需要将其更改为两个表,一个用于文本,另一个用于链接到该文本的类别。@JafarElahi没有问题。如果你能正常化你的表,我建议你这样做。好方法!但我认为绩效将不会有效率。因为产品表是一个大表,它的字符串操作实际上是很低的。当JavaRaLaHi与一个归一化表进行比较时,性能将低于标准,因为我们将ItID ID存储为int。然而,如果你被设计所困扰,你可以走这条路线。在我的机器上,查询花了4秒钟的时间处理了一百万行。