具有动态列和百分比匹配的匹配和排名查询

发布于 2024-10-27 05:24:32 字数 2301 浏览 4 评论 0 原文

我正在尝试为客户编写一个排名匹配/搜索系统,该系统将查看所请求的材料(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)  

,例如,如果我有这个请求:

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)

并且填充了 MaterialProvider,就像

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  

从请求中的材料派生出列名称一样。然后能够找到能够提供超过给定百分比的所需材料的提供商。

我从一个临时表和一个游标开始,将

  1. 列添加到临时表中
  2. ,然后迭代 3000 多个提供者并添加那些可以提供指定材料的提供者。

有更好的方法吗?这个过程花费的时间太长,希望获得关于如何编写这样的内容的更好/最佳实践。

I'm trying to write a ranked match/searching system for a client that will look at the materials requested (MaterialRequest table) and find the providers (where userprofile.usertype_id = 1) who can provide the material(s) and rank the results that can provide the most, or all of the, materials. Here's the database schema i have:

Userprofile Table

userprofile_id   int identity  
userprofile_dt   datetime  
first_nm         varchar(50)  
last_nm          varchar(50)  
usertype_id      int (provider = 1, requestor = 2)  

Request Table

request_id       int identity  
request_dt       datetime  
title            varchar(50)  
description      varchar(100)  
userprofile_id   int (where usertype = 2)  

MaterialRequest Table

material_req_id  int identity  
request_id       int  
material_id      int  

MaterialProvider Table

material_pro_id  int identity  
userprofile_id   int (where usertype = 1)  
material_id      int

Material Table

material_id      int identity  
material_desc    varchar(50)  

So, for example, if I have this request:

request_id = 1  
request_dt = 3/28/2011  
title = 'test request'  
desc = null  
userprofile_id = 100 (where usertype_id = 2)  

and these materials were requested

material_req_id   request_id   material_id
1                 1            10 (steel)
2                 1            11 (copper)
3                 1            12 (titanium)
4                 1            13 (nickel)

and the MaterialProvider was populated like

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)  

I would expect my output to look like

userprofile_id    steel    copper    nickel    titanium    pct_match  
2                 Y        Y         Y         N           75  
3                 N        Y         Y         Y           75  

where the column names are derived from the materials in the request. Then be able to find the providers that can provide more than a given percentage of the materials requested.

I had started with a temporary table and a cursor to

  1. add the columns to the temporary table
  2. then iterate through the 3000+ providers and add those providers that can provide the specified materials.

Is there a better way to do this? The process takes way too long and would like to get better/best practices on how to write something like this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

年华零落成诗 2024-11-03 05:24:32
;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
;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
想念有你 2024-11-03 05:24:32

在确定一组目标提供商之后,最后对材料名称进行透视。首先进行所有数学计算,然后进行漂亮的格式化。

Do the pivot on the materials name last, after you've identified a set of target providers. Do all the math first, then the pretty formatting.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文