Sql server 具有动态列和百分比匹配的匹配和排序查询
我正在尝试为客户编写一个排名匹配/搜索系统,该系统将查看所请求的材料(MaterialRequest表),并找到能够提供材料的提供者(其中userprofile.usertype_id=1),并对能够提供最多或全部材料的结果进行排名。以下是我的数据库模式: 用户配置文件表Sql server 具有动态列和百分比匹配的匹配和排序查询,sql-server,stored-procedures,database-cursor,Sql Server,Stored Procedures,Database Cursor,我正在尝试为客户编写一个排名匹配/搜索系统,该系统将查看所请求的材料(MaterialRequest表),并找到能够提供材料的提供者(其中userprofile.usertype_id=1),并对能够提供最多或全部材料的结果进行排名。以下是我的数据库模式: 用户配置文件表 userprofile_id int identity userprofile_dt datetime first_nm varchar(50) last_nm varch
userprofile_id int identity
userprofile_dt datetime
first_nm varchar(50)
last_nm varchar(50)
usertype_id int (provider = 1, requestor = 2)
request_id int identity
request_dt datetime
title varchar(50)
description varchar(100)
userprofile_id int (where usertype = 2)
material_req_id int identity
request_id int
material_id int
material_pro_id int identity
userprofile_id int (where usertype = 1)
material_id int
material_id int identity
material_desc varchar(50)
请求表
userprofile_id int identity
userprofile_dt datetime
first_nm varchar(50)
last_nm varchar(50)
usertype_id int (provider = 1, requestor = 2)
request_id int identity
request_dt datetime
title varchar(50)
description varchar(100)
userprofile_id int (where usertype = 2)
material_req_id int identity
request_id int
material_id int
material_pro_id int identity
userprofile_id int (where usertype = 1)
material_id int
material_id int identity
material_desc varchar(50)
材料要求表
userprofile_id int identity
userprofile_dt datetime
first_nm varchar(50)
last_nm varchar(50)
usertype_id int (provider = 1, requestor = 2)
request_id int identity
request_dt datetime
title varchar(50)
description varchar(100)
userprofile_id int (where usertype = 2)
material_req_id int identity
request_id int
material_id int
material_pro_id int identity
userprofile_id int (where usertype = 1)
material_id int
material_id int identity
material_desc varchar(50)
材料供应表
userprofile_id int identity
userprofile_dt datetime
first_nm varchar(50)
last_nm varchar(50)
usertype_id int (provider = 1, requestor = 2)
request_id int identity
request_dt datetime
title varchar(50)
description varchar(100)
userprofile_id int (where usertype = 2)
material_req_id int identity
request_id int
material_id int
material_pro_id int identity
userprofile_id int (where usertype = 1)
material_id int
material_id int identity
material_desc varchar(50)
材料表
userprofile_id int identity
userprofile_dt datetime
first_nm varchar(50)
last_nm varchar(50)
usertype_id int (provider = 1, requestor = 2)
request_id int identity
request_dt datetime
title varchar(50)
description varchar(100)
userprofile_id int (where usertype = 2)
material_req_id int identity
request_id int
material_id int
material_pro_id int identity
userprofile_id int (where usertype = 1)
material_id int
material_id int identity
material_desc varchar(50)
例如,如果我有这个请求:
request_id = 1
request_dt = 3/28/2011
title = 'test request'
desc = null
userprofile_id = 100 (where usertype_id = 2)
这些材料是需要的
material_req_id request_id material_id
1 1 10 (steel)
2 1 11 (copper)
3 1 12 (titanium)
4 1 13 (nickel)
材料提供者的人口是这样的
material_pro_id userprofile_id material_id
1 2 10 (steel)
2 2 11 (copper)
3 2 13 (nickel)
4 3 11 (copper)
5 3 13 (nickel)
6 3 12 (titanium)
我希望我的输出看起来像
userprofile_id steel copper nickel titanium pct_match
2 Y Y Y N 75
3 N Y Y Y 75
其中,列名源自请求中的材料。然后能够找到能够提供超过所需材料给定百分比的供应商
我从一个临时表和一个光标开始
有更好的方法吗?该过程耗时太长,希望在如何编写类似内容方面获得更好的/最佳实践。在确定一组目标提供者后,最后再围绕材料名称进行重点讨论。首先做所有的数学运算,然后再做漂亮的格式化。在确定一组目标提供者之后,最后做材质名称的轴心。先做所有的数学题,然后是漂亮的格式。Y/N在您的预期输出中代表什么?Y/N表示供应商是否可以提供该列表示的材料。Y/N在您的预期输出中代表什么?Y/N表示供应商是否可以提供该列表示的材料。
;WITH NormalOutput AS (
/* normal output: one material per row */
SELECT
p.userprofile_id,
m.material_desc,
value = CASE WHEN mp.material_pro_id IS NULL THEN 'N' ELSE 'Y' END
FROM Request r
INNER JOIN MaterialRequest mr ON r.request_id = mr.request_id
INNER JOIN Material m ON mr.material_id = m.material_id
CROSS JOIN (SELECT DISTINCT userprofile_id FROM MaterialProvider) p
LEFT JOIN MaterialProvider mp
ON p.userprofile_id = mp.userprofile_id AND mr.material_id = mp.material_id
WHERE r.request_id = 1
)
SELECT p.*, t.pct_match
FROM (
/* pivoting the normal output */
SELECT userprofile_id, steel, copper, titanium, nickel
FROM NormalOutput n
PIVOT (MAX(value) FOR material_desc IN (steel, copper, titanium, nickel)) p
) p
INNER JOIN (
/* aggregating the normal output (calculating percents) */
SELECT
userprofile_id,
pct_match = COUNT(CASE value WHEN 'Y' THEN value END) * 100 / COUNT(*)
FROM NormalOutput
GROUP BY userprofile_id
) t
/* joining the two modified outputs */
ON t.userprofile_id = p.userprofile_id