【问题标题】:SQL Server Dynamic Search Based on Stored Search Parameters基于存储搜索参数的 SQL Server 动态搜索
【发布时间】:2017-03-20 14:01:21
【问题描述】:

我必须创建一个动态搜索。搜索条件存储在表中,存储记录有一个主表。这是结构:

--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' 的记录。结果只是@Records 表中的“C”。如果我在所有表上创建左连接,我也会获得 ownerId '100' 的其他记录。如果我在表中包含一个内部联接,如果@CriteriaCities 或@CriteriaFriend 表中没有条件条目,我将不会得到任何记录。根据链接表(@CriteriaCities,@CriteriaFriend)中存在的记录搜索主表中记录的查询应该是什么?如果搜索参数未存储在这些表中,则不应在这些表之间创建连接。

【问题讨论】:

  • 为什么会有这么复杂的过程?这种设计的原因是什么?此外,在您的示例中,如果您正在搜索 101、102 或 103 的 CityID 和 201 的 FriendID,则不匹配文件 A 和 B C 的?即使您根据脚本使用FriendID 或202。你会匹配A和C。您如何将 File C 作为输出?

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


【解决方案1】:

我不确定您是否完全理解了您的逻辑,因为根据我的评论,您的问题不太有意义,但如果我遵循您所说的作为您的规则,您可以使用以下 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
        );

【讨论】:

  • 是的。你是对的。 FriendId“202”会给A和C。我的错误。我刚刚创建了临时表并混合了实际值。无论如何,根据您的回答,如果“@CriteriaFriend”表中没有 [OwnerId] 100 的记录,则结果将为空白。而我的要求是“如果“@CriteriaFriend”表中没有记录,则不要创建连接。“@CriteriaCities”表也是如此。
  • 这行得通,尽管我不得不做一些调整。谢谢!
【解决方案2】:

抱歉,我无法理解您的输出。 为什么你应该只得到 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
)

【讨论】:

    猜你喜欢
    • 2012-05-03
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 2011-06-03
    • 2015-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多