mysql - 如何在一对多关系中选择每个匹配行的最小(最大)?
问题描述
我有三张桌子,例如fruits
:
+----+--------+---------+
| id | type | variety |
+----+--------+---------+
| 1 | orange | 5 |
| 2 | orange | 7 |
| 3 | apple | 1 |
| 4 | apple | 0 |
+----+--------+---------+
containers
:
+----+--------+
| id | year |
+----+--------+
| 1 | 2015 |
| 2 | 2020 |
| 3 | 2020 |
| 4 | 2018 |
+----+--------+
和inclusion
:
+----+----------+---------+
| id | fruit_id | cont_id |
+----+----------+---------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 3 | 2 |
| 5 | 3 | 3 |
| 6 | 3 | 4 |
+----+----------+---------+
如果有的话,我需要为每个水果品种选择“最新”的容器:
+----+--------+----------+------+
| id | type | variety | year |
+----+--------+----------+------+
| 1 | orange | 5 | 2020 |
| 2 | orange | 7 | 2015 |
| 3 | apple | 1 | 2020 |
| 4 | apple | 0 | NULL |
+----+--------+----------+------+
我正在尝试类似的东西
SELECT * FROM `fruits`
LEFT JOIN (SELECT * FROM `containers`
JOIN `inclusion` ON `inclusion`.`cont_id` = `containers`.`id`
WHERE `fruit_id` = `fruits`.`id`
ORDER BY `year` DESC LIMIT 1
) `tops` ON `tops`.`fruit_id` = `fruits`.`id`;
但它说
ERROR 1054 (42S22): Unknown column 'fruits.id' in 'where clause'
有没有办法得到所需的结果?
我现在正在使用mariadb
我的,但可能会迁移到mysql
,所以我需要一个在两台服务器上都可以工作的解决方案。
如果我还添加cnt_type
表怎么办:
+----+---------+
| id | type |
+----+---------+
| 1 | box |
| 2 | package |
+----+---------+
并将containers
包括类型:
+----+--------+------+
| id | year | type |
+----+--------+------+
| 1 | 2015 | 1 |
| 2 | 2020 | 1 |
| 3 | 2020 | 2 |
| 4 | 2018 | 2 |
+----+--------+------+
所以我需要提取每种容器类型的顶级年份,包括每种水果品种?
+----+--------+----------+----------+------+
| id | type | variety | cnt_type | year |
+----+--------+----------+----------+------+
| 1 | orange | 5 | box | 2020 |
| 1 | orange | 5 | package | NULL |
| 2 | orange | 7 | box | 2015 |
| 2 | orange | 7 | package | NULL |
| 3 | apple | 1 | box | 2020 |
| 3 | apple | 1 | package | 2020 |
| 4 | apple | 0 | box | NULL |
| 4 | apple | 0 | package | NULL |
+----+--------+----------+----------+------+
在这种情况下,组合type
-year
每个容器都应该是唯一的。
解决方案
如果你最终坚持使用 MySQL 5.7(并且没有窗口函数),你可以使用这个查询(它也适用于 MariaDB)。该问题可以通过一个相当简单的选择来解决,该选择MAX(containers.year)
按水果中的所有列和容器类型进行分组。需要注意 aCROSS JOIN
以确保所有水果/容器组合都包含在输出中:fruits
cnt_type
SELECT f.id, f.type, f.variety,
ct.type AS cnt_type,
MAX(c.year) AS year
FROM fruits f
CROSS JOIN cnt_type ct
LEFT JOIN inclusion i ON i.fruit_id = f.id
LEFT JOIN containers c ON c.id = i.cont_id AND c.type = ct.id
GROUP BY f.id, f.type, f.variety, ct.type
输出:
id type variety cnt_type year
1 orange 5 box 2020
1 orange 5 package null
2 orange 7 box 2015
2 orange 7 package null
3 apple 1 box 2020
3 apple 1 package 2020
4 apple 0 box null
4 apple 0 package null
推荐阅读
- c - ANSI C (C89) 中的 Stdint.h
- vue.js - 如何在vue中使用对象重定向到页面
- python - Python Scrapy 的元标记问题。选定字段的 KeyError
- linux - 将 Cron 与 Bash 脚本一起使用时导致多封邮件的原因
- scala - Spark Scala 将 Int 列转换为日期时间
- java - Spring RestController 不显示 html 页面,仅显示文本
- azure - 我应该在生产环境中使用 Azure AD SAML 工具包吗?
- sas - 是否有一种简单的方法可以在 SAS 中复制存储过程?
- c++ - 使我的函数调用 async_read 异步 Boost::asio
- react-native - 多个过滤器/过滤器内过滤器 - React Native