基于存储搜索参数的SQL Server动态搜索

时间:2016-11-07 09:19:20

标签: sql-server tsql sql-server-2012

我必须创建一个动态搜索。搜索条件存储在表中,并且存储了记录的主表。结构如下:

--Main Table. This table stores records of a user. Basically we store files in this table. Each file is associated with a single city.
DECLARE @Records TABLE(
[RecordId] INT IDENTITY(1,1),
[FileName] VARCHAR(100),
[OwnerId] INT,
[CityId] INT
)
INSERT INTO @Records
SELECT 'A', 100, 101 UNION
SELECT 'B', 100, 102 UNION
SELECT 'C', 100, 103 UNION
SELECT 'D', 100, 104

--The next table is used to associate a file with multiple friends.
DECLARE @FriendRecords TABLE
(
[Id] INT IDENTITY(1,1),
[RecordId] INT,
[FriendId] INT
)
INSERT INTO @FriendRecords
SELECT 1, 201 UNION --File '1' is associated with 'FriendId' 201
SELECT 1, 202 UNION --File '1' is associated with 'FriendId' 202
SELECT 2, 201 UNION --File '2' is associated with 'FriendId' 201
SELECT 3, 202       --File '3' is associated with 'FriendId' 202

--The following table is used to create a criteria for user.
DECLARE @Criteria TABLE
(
[CriteriaId] INT IDENTITY(1,1),
[CriteriaName] VARCHAR(50),
[OwnerId] INT
)
INSERT INTO @Criteria
SELECT 'SampleCriteria', 100 --Criteria created by user 100

--The following table is used to store cities that needs to be searched in 'Records' table for owner of criteriaId '1'.
DECLARE @CriteriaCities TABLE(
[CriteriaCityId] INT IDENTITY(1,1),
[CriteriaId] INT, 
[CityId] INT
)
INSERT INTO @CriteriaCities
SELECT 1, 101 UNION
SELECT 1, 102 UNION
SELECT 1, 103 

--The following table is used to store friend that needs to be searched in 'FriendsRecords' table for owner of criteriaId '1'.
DECLARE @CriteriaFriend TABLE(
[CriteriaCityId] INT IDENTITY(1,1),
[CriteriaId] INT, 
[FriendId] INT
)
INSERT INTO @CriteriaFriend
SELECT 1, 202;

基本上,用户可以创建条件(@Criteria表)并存储搜索参数(@CriteriaCities和@CriteriaFriend表)。要求是根据存储的条件获取文件。我正在寻找的查询应该从@Records表中返回记录,该表具有cityIds 101,102& 103 AND FriendId' 201'。结果只有' C'来自@Records表。如果我在所有表格上创建左连接,我会获得ownerId' 100'的其他记录。同样。如果我在表中包含内部联接,如果@CriteriaCities或@CriteriaFriend表中没有条件条目,则我没有记录。根据链接表中存在的记录(@CriteriaCities,@ CriteriaFriend),在主表中搜索记录的查询应该是什么?如果搜索参数未存储在这些表中,则不应在这些表之间创建连接。

2 个答案:

答案 0 :(得分:0)

我不确定您的逻辑是否完全被理解,因为我的评论对您的问题没有多大意义,但如果我按照您所说的规则进行操作,则可以使用以下select声明获取您的数据。我不知道你将如何传递你正在搜索的标准,因为你还没有解释你的过程的这部分如何运作:

-- Count the records in each criteria table.
declare @CriteriaCitiesCount int = (select count(1) from @CriteriaCities);
declare @CriteriaFriendCount int = (select count(1) from @CriteriaFriend);


select *
from @Records r
    left join @CriteriaCities cc
        on(r.CityId = cc.CityId)
    left join @FriendRecords f
        on(r.RecordId = f.RecordId)
    left join @CriteriaFriend cf
        on(f.FriendId = cf.FriendId)
where (@CriteriaCitiesCount = 0        -- Only return records where we aren't filtering,
        or cc.CityId is not null       -- Or we are filtering and we get a match.
        )
    and (@CriteriaFriendCount = 0
        or cf.FriendId is not null
        );

答案 1 :(得分:0)

抱歉,我无法理解您的输出。 为什么你应该只得到FileName C?

尝试类似的事情,

;With CTE as
(
select cc.CityId,cf.FriendId    
from @Criteria C
inner join @CriteriaCities CC
on c.CriteriaId=cc.CriteriaId
inner join @CriteriaFriend CF  
on c.CriteriaId=cf.CriteriaId
where c.OwnerId=@ownerid
)

select *
from @Records R
inner join @FriendRecords FR
on r.RecordId=fr.RecordId
where EXISTS(
select cityid from cte c where r.CityId=c.cityid and c.FriendId=fr.FriendId
)