Sql server 具有动态列和百分比匹配的匹配和排序查询

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

我正在尝试为客户编写一个排名匹配/搜索系统,该系统将查看所请求的材料(MaterialRequest表),并找到能够提供材料的提供者(其中userprofile.usertype_id=1),并对能够提供最多或全部材料的结果进行排名。以下是我的数据库模式:

用户配置文件表

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  
其中,列名源自请求中的材料。然后能够找到能够提供超过所需材料给定百分比的供应商

我从一个临时表和一个光标开始

  • 将列添加到临时表中
  • 然后遍历3000多个提供者,添加那些可以提供指定材料的提供者
    有更好的方法吗?该过程耗时太长,希望在如何编写类似内容方面获得更好的/最佳实践。

    在确定一组目标提供者后,最后再围绕材料名称进行重点讨论。首先做所有的数学运算,然后再做漂亮的格式化。

    在确定一组目标提供者之后,最后做材质名称的轴心。先做所有的数学题,然后是漂亮的格式。

    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