mysql - 非等价连接

标签 mysql sql sql-server oracle postgresql

我已经使用 SQL 好几年了,在这段时间里,我对连接的想法是等价连接,如在

select ... from t1 join t2 on t1.a = t2.b

注意连接是如何基于一个或多个等式的,这里是 t1.a = t2.b。但是,最近,我不记得在哪里,我看到了一个非等价连接(我只是杜撰了这个词,请告诉我它是否有真实的名称),其中连接条件至少包含一个不相等,如

select ... from t1 join t2 on t1.a > t2.b

这可以用来做一些不错的事情,尤其是外连接。让我用一个例子来说明这一点。

让我们考虑一个名为 products 的表,其中包含以下数据:

product   year  price
----------------------
apple   2009    4
apple   2008    2
apple   2007    5
apple   2006    6
apple   2005    2
banana  2009    9
banana  2008    12
banana  2007    16
banana  2006    15
banana  2005    10

而且我们想像往常一样“为每种产品提供最昂贵的年份”,据我所知,这通常是通过对按产品分组的同一个表进行内部联接来完成的,如下所示:

select t1.`name`, t1.`year`, t1.`price`
from products as t1 join
( select `name`, max(`price`) as `max_price` from products group by `name` ) as t2 on t1.`name`=t2.`name` and t1.`price`=t2.`max_price`

因此,在 t2,我们获得了每种产品的最高价格,然后我们将此结果与同一个表连接起来,以获取该列的其余数据(打破平局有点棘手)

但是,对于非等价外连接,我们可以这样做:

select t1.`name`, t1.`year`, t1.`price`
from products as t1 left join products as t2 on t1.`name`=t2.`name` and t1.`price` < t2.`price`
where t2.`name` is null

这一次,我们加入同一张表两次,其中 t1 上的价格低于 t2 上的价格。这里的技巧是,由于这是一个左外连接,当连接不匹配时,结果连接上的 t2 值将为空,这发生在价格的最大值。

这两个查询产生相同的结果,但我不确定哪个执行得更好。第一个查询有一个昂贵的分组,而第二个查询必须手动检查所有 t1/t2 对以获得结果。不过,使用非等价连接似乎更容易打破平局。

所以,我的问题是:

是否有任何推荐的资源(书籍、网页)更深入地讨论非等价连接,解释您可以用它们做什么(我假设您可以做的不仅仅是获取组中的最大值),以及在做同样的事情时,它们与其他方法相比表现如何?

编辑:我知道窗口函数也可用于执行我上面提到的简单示例等操作。我不是在问如何获得表格的最大值。我知道如何做到这一点,我什至提供了两种方法来做到这一点。我想知道我还能用非等价连接做些什么。

最佳答案

And we want to do the usual "give me the most expensive year for each product", which is, as far as I know, commonly done with an inner join to the same table grouped by products, like so

使用窗口函数更容易完成(正如 jonealres 已经提到的)

select name, 
       year, 
       price,
       max(price) over (partition by name) as most_expensive
from products

关于mysql - 非等价连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5415497/

相关文章:

sql - PostgreSQL 插入触发器和多对多表

sql - 使用动态 SQL 时列名无效

MySQL: "lock wait timeout exceeded"

php - MySQL SELECT COUNT 从 PHP 中的多个表

sql - PostgreSql 中的 Select For Update 语句

sql - 你能告诉我数据是什么时候插入到表中的吗

sql-server - Azure SQL - 使用弹性数据库查询从另一个数据库查询现有表

sql-server - WAS 8.5 在故障转移处理具有 JNDI 名称 XXX 的资源时无法找到主池管理器

php - 避免在 PHP 中显示来自数据库的重复结果

php - 如何从嵌套连接查询中进行选择