【问题标题】:Matching algorithm in SQLSQL中的匹配算法
【发布时间】:2014-06-18 12:54:00
【问题描述】:

我的数据库中有下表。

# select * FROM matches;
 name | prop |  rank
------+------+-------
 carl |    1 |     4
 carl |    2 |     3
 carl |    3 |     9
 alex |    1 |     8
 alex |    2 |     5
 alex |    3 |     6
 alex |    3 |     8
 alex |    2 |    11
 anna |    3 |     8
 anna |    3 |    13
 anna |    2 |    14
(11 rows)

每个人在工作中根据称为“道具”的不同属性/标准进行排名,绩效称为“排名”。如示例所示,该表包含 (name, prop) 的多个值。我想从一些要求中得到最好的候选人。例如。我需要一个拥有(prop=1 AND rank > 5)(prop=3 AND rank >= 8) 的候选人。然后我们必须能够根据他们的排名对候选人进行排序,以获得最佳候选人。

编辑:每个人都必须满足所有要求

如何在 SQL 中执行此操作?

【问题讨论】:

  • 您能在问题中添加想要的结果吗?
  • 这真的很初级。搜索“SELECT WHERE ORDER BY sql 示例”
  • 您应该考虑数据规范化。如果我理解正确,您需要在这两个条件下进行标准自加入,然后是 order-by 语句。
  • 如果候选人对选定的prop 有多个rank,你想得到什么?更具体地说,如果他们的队伍中有 一些 通过了您的条件 一些 则没有。
  • @EnnoShioji:这是一个误解。关系除法根本不是基本的。

标签: sql postgresql relational-division


【解决方案1】:
select x.name, max(x.rank) 
from matches x
join (
    select name from matches where prop = 1 AND rank > 5
    intersect
    select name from matches where prop = 3 AND rank >= 8
) y
    on x.name = y.name 
group by x.name
order by max(rank);

【讨论】:

  • max(x.rank) 失败,因为大多数排名值将来自 y - 您忘记包含 rank ...
  • @Erwin,不确定我是否理解您的评论,Y 是一个派生表,由同时满足两个条件的名称组成。秩不能是 y 的一部分,因为这意味着在两种情况下秩必须相同。另一方面,x 包含这些用户的所有等级。你能举一个查询失败的例子吗?
  • 啊,我明白了。我的想法。您将重新加入 matches 并检索每个合格名称的 all 行。所以我的说法是错误的。
  • 之前的查询有错别字,我在 y 中没有表,所以可能搞砸了,抱歉。
【解决方案2】:

在这里过滤数据以匹配您的标准非常简单(如 Amir 和 sternze 所示):

SELECT *
FROM matches
WHERE prop=1 AND rank>5) OR (prop=3 AND rank>=8

问题是如何聚合这些数据以使每个候选者只有一行。

我建议你这样做:

SELECT m.name,
   MAX(DeltaRank1) AS MaxDeltaRank1,
   MAX(DeltaRank3) AS MaxDeltaRank3
FROM (
  SELECT name,
    (CASE WHEN prop=1 THEN rank-6 ELSE 0 END) AS DeltaRank1,
    (CASE WHEN prop=3 THEN rank-8 ELSE 0 END) AS DeltaRank3,
  FROM matches
) m
GROUP BY m.name
HAVING MaxDeltaRank1>0 AND MaxDeltaRank3>0
SORT BY MaxDeltaRank1+MaxDeltaRank3 DESC;

这将根据他们在 prop1 和 prop3 中超出目标排名的总和对候选人进行排序。不过,您可以使用不同的逻辑来指示哪个是最好的。

在上面的例子中,结果应该是这样的:

 name | MaxDeltaRank1 | MaxDeltaRank3
------+---------------+--------------
 alex |       3       |       0

...因为 anna 和 carl 都没有达到要求的等级。

【讨论】:

    【解决方案3】:

    关系划分的典型案例。我们在这个相关问题下组装了一整套技术:
    How to filter SQL results in a has-many-through relation

    假设你想要一个人的最低等级,我可能会用LEAST()解决你的特殊情况:

    SELECT m1.name, LEAST(m1.rank, m2.rank, ...) AS best_rank
    FROM   matches m1
    JOIN   matches m2 USING (name)
    ...
    WHERE  m1.prop = 1 AND m1.rank >  5 
    AND    m2.prop = 3 AND m2.rank >= 8
    ...
    ORDER  BY best_rank;
    

    还假设name 对于每个人都是唯一的。实际上,您可能会对 person 表的 pk 列使用某种外键。
    如果您有这样的person 表,那么最好的排名将存储在那里的列中......

    【讨论】:

      【解决方案4】:

      如果我理解你的问题,那么你只需要执行以下操作:

      SELECT * FROM matches where (prop = 1 AND rank > 5) OR (prop = 3 AND rank >= 8) ORDER BY rank
      

      它为您提供 prop=1 且排名 > 5 或 prop=3 且排名 >= 8 的候选人,按他们的排名排序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-18
        • 1970-01-01
        • 2011-06-18
        • 2018-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-11
        相关资源
        最近更新 更多