跳转到内容

PostgreSQL/不使用消除的 SELECT

来自维基教科书,开放的书籍,开放的世界

使用布尔条件来缩小一组数据而不消除所有可能的结果,这是 SQL 中常见的难题。在这个例子中,你想要找到最佳匹配,如果可以的话,或者NULL. 这可以通过关系型数据库轻松干净地实现,方法是稍微滥用一下UNION ALL。有很多方法可以用过程化的方式来实现,例如模糊匹配。[1]


基本思路是SELECT *,不消除任何内容,UNION ALL到同一个集合上的另一个SELECT(不同的实例),这样就有可能在 UNION 的集合中消除元组。然后你会count()所有元组的出现次数,每个元组至少出现一次(第一个UNION ALL的 LHS),这将不会导致任何消除。对于这个结果集,你将选择count()max()

db=# select * from foo;
 bar 
-----
   5
   4
   3
   6
(4 rows)

SQL 非消除条件

[编辑 | 编辑源代码]
SELECT count(foo.bar), bar
FROM (
     SELECT *
     FROM foo

     UNION ALL

     SELECT *
     FROM foo
     WHERE bar = 4 -- Conditional that will not eliminate
)
AS foo
GROUP BY bar
;

这里关键的是,如果使用了条件bar = 50,你仍然会得到原始数据集。

 count | bar 
-------+-----
     1 |   5
     2 |   4
     1 |   3
     1 |   6
(3 rows)

第三方数据提供商给了你一组数据,你希望从中选择最佳匹配。你配备了一些可能帮助你识别最佳匹配的东西,但你希望始终返回一个元组,也就是说你永远不想消除所有返回的元组。你的数据应该只裁剪掉多余的匹配项。

例如,我们使用一个 vin1GCEC14C57Z590788:

  • 他们称修剪为 "Work Truck",你称修剪为 "1WT"。

想因为这一点而消除所有车辆。因此,这里使用条件trim LIKE '%1WT%'将不起作用,因为 "Work Truck" 中不包含 "1WT"。

现在假设其他提供的信息将帮助你更好地识别你的车辆与哪种风格相匹配。就像 "MSRP" 的情况一样,如果它在 18,123 的 1.00 美元范围内,你就可以成功地消除除一种风格之外的所有风格。

观察我们可以做到这一点的一种方法

  1. ^ 模糊匹配通常使用简单的莱文斯坦编辑距离公式。使用 plperl(Perl),你可以使用String::Approx 模块的adist()轻松地实现这一点。
华夏公益教科书