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