好的,所以这个特殊的用例让我有点头疼。
这是另一篇文章的编辑,我忘记在用例中添加一个重要方面。
需要做的是将候选人 WorkWish 与数据库中的 CustomerJobQueries 相匹配。
这意味着,如果 WorkWish 中的日期时间与任何 CustomerJobQueries 重叠,则匹配。然后我需要将 GeographicalPreference 与客户的位置相匹配。
我们构建数据库时的逻辑是:
可能存在多个行,因此设置了2个特定的城市,唯一的规则是永远不会存在优先于另一个的行。
含义
GeographicalPreferenceId Country_ShortName Region_Id Municipality_Id WorkWish_Id
------------------------ -------------------- ----------- --------------- -----------
1 DK NULL NULL 1
2 DK 3 NULL 1
不可能,因为有一行已经指明他希望在整个国家/地区工作。
这就是数据库片段的样子
DateRange表 - 包含所有DateRanges
DateRangeId StartDate EndDate CustomerJobQuery_Id WorkWish_Id
----------- --------------------------- --------------------------- ------------------- -----------
1 2014-03-31 00:00:00.0000000 2014-08-18 00:00:00.0000000 NULL 1
2 2014-08-25 00:00:00.0000000 2014-09-15 00:00:00.0000000 NULL 1
3 2013-08-24 00:00:00.0000000 2014-09-25 00:00:00.0000000 1 NULL
工作愿望表
Id Candidate_Id
----------- ------------
1 5
CustomerJobQuery表
Id Customer_CustomerId Country_ShortName Region_Id Municipality_Id
----------- ------------------- ----------------- --------- -----------------
1 2 DK 2 3
地理位置表
GeographicalPreferenceId Country_ShortName Region_Id Municipality_Id WorkWish_Id
------------------------ -------------------- ----------- --------------- -----------
1 DK 2 NULL 1
2 DK 3 NULL 1
到目前为止是什么; - 返回与WorkWish日期重叠的CustomerJobQueries。
SELECT c.*
FROM CustomerJobQuery c
WHERE EXISTS (
SELECT *
FROM Workwish w
INNER JOIN DateRange d1 ON d1.CustomerJobQuery_Id = c.Id
INNER JOIN DateRange d2 ON d2.WorkWish_Id = w.Id
WHERE w.Candidate_Id = @CandidateId -- input from my **StoredProcedure**
-- overlap check:
AND d1.StartDate <= d2.EndDate
AND d2.StartDate <= d1.EndDate
)
我不确定如何以集合方式执行地理偏好逻辑。 - 目前我们的解决方案是在C#中将所有内容加载到内存中,并使用嵌套的foreach循环遍历所有内容,这非常无效。并且是绝对最糟糕的情况。
非常感谢任何帮助!
答案 0 :(得分:1)
我创建了一些表,因为你没有提供任何DDL。
declare @CandidateId int;
declare @WorkWish table (
Id int primary key,
CandidateId int
);
declare @Preference table (
Id int primary key,
WishId int,
Country char(2),
RegionId int null,
MunicipalityId int null
);
declare @DateRange table (
Id int primary key,
StartDate datetime,
EndDate datetime,
JobQueryId int null,
WishId int null
);
declare @JobQuery table (
Id int primary key,
CustomerId int,
Country char(2),
RegionId int,
MunicipalityId int
);
select *,
case
when p.MunicipalityId is not null then 0
when p.RegionId is not null then 1
else 2
end as [LocationMetric]
from @WorkWish w
inner join @Preference p on w.Id = p.WishId
inner join @DateRange dw on dw.WishId = w.Id
inner join @JobQuery j on j.Country = p.Country
inner join @DateRange dj on dj.JobQueryId = j.Id
where w.CandidateId = @CandidateId
and dw.StartDate <= dj.EndDate
and dj.StartDate <= dw.EndDate
and nullif(p.RegionId, j.RegionId) is null
and nullif(p.MunicipalityId, j.MunicipalityId) is null
order by LocationMetric;
我必须警告你关于NULLIF()
函数的性能,但是它还远非完美。您可以尝试将其扩展为相应的case
构造,但通常不值得努力。
不过,它应该比你现在拥有的更好。
答案 1 :(得分:0)
我认为以下内容将为您提供所有匹配:
WITH ww as (
SELECT ww.*, drw.StartDate, drw.EndDate
FROM WorkWish ww JOIN
DateRange drw
ON drw.WorkWish_Id = w.id
)
SELECT c.*
FROM CustomerJobQuery c JOIN
DateRange drc
ON drc.CustomerJobQuery_Id = c.id JOIN
ww
ON drc.StartDate <= ww.EndDate AND ww.StartDate <= drw.EndDate AND
(drc.Country_ShortName = ww.Country_ShortName and ww.Region_id is NULL or
drc.Country_ShortName = ww.Country_ShortName and drc.Region_id = ww.Region_id and ww.municipality_id is null or
drc.Country_ShortName = ww.Country_ShortName and drc.Region_id = ww.Region_id and drc.Municipality_Id = ww.Munipality_Id
)
)
如果要确定匹配的优先级,请使用row_number()
和子查询:
WITH ww as (
SELECT ww.*, drw.StartDate, drw.EndDate
FROM WorkWish ww JOIN
DateRange drw
ON drw.WorkWish_Id = w.id
)
SELECT c.*
FROM (SELECT c.*, ww.id as WorkId,
ROW_NUMBER() OVER (PARTITION BY c.id
ORDER BY (case when ww.Munipality_Id is not null then 1
when ww.Region_id is not null then 2
else 3
end)
) as seqnum
FROM CustomerJobQuery c JOIN
DateRange drc
ON drc.CustomerJobQuery_Id = c.id JOIN
ww
ON drc.StartDate <= ww.EndDate AND ww.StartDate <= drw.EndDate AND
(drc.Country_ShortName = ww.Country_ShortName and ww.Region_id is NULL or
drc.Country_ShortName = ww.Country_ShortName and drc.Region_id = ww.Region_id and ww.municipality_id is null or
drc.Country_ShortName = ww.Country_ShortName and drc.Region_id = ww.Region_id and drc.Municipality_Id = ww.Munipality_Id
)
) c
WHERE seqnum = 1;