mysql - MySQL:我需要根据某些条件返回行
问题描述
我有 3 张桌子:工作、录音、发布
1 个作品可以有多个录音,1 个录音仅出现在 1 个版本中
表:工作
+---------+-----------+
| work_id | name |
+---------+-----------+
| 1 | Hello |
| 3 | Luna |
| 4 | Feel good |
| 5 | My self |
+---------+-----------+
表:记录
+---------------------------------------------------------------------+
| recording_id | work_id | release_id | name | is_art | is_vid |
+---------------------------------------------------------------------+
| 45 | 1 | 45 | Hello4 | 1 | 0 |
| 78 | 3 | 67 | Luna5 | 1 | 0 |
| 23 | 5 | 128 | My self (r) | 1 | 0 |
| 95 | 5 | 156 | My self II | 1 | 0 |
| 17 | 4 | 67 | Luna67 | 1 | 0 |
+---------------------------------------------------------------------+
表:发布
+--------------------------------------------+
| release_id | name | year | month | day |
+--------------------------------------------+
| 45 | Yo | 1998 | 12 | NULL |
| 67 | Testing | 1967 | 3 | 3 |
| 128 | Maybe | 2018 | 10 | 21 |
| 156 | Again | 2018 | 10 | NULL |
+--------------------------------------------+
基本上,对于每个work
,我想返回recording
whereis_art = 1
和is_vid = 0
ANDrelease
是最旧的(最旧的年、月和日)。我可能是 arecording
release
可以具有相同的year
,month
和day
. 在那种情况下,我想我需要找到一个唯一的标识符,所以我会选择最新的release_id
结果集应如下所示:
+---------+---------------------------------------+
| work_id | name | recording_id | name |
+---------+---------------------------------------+
| 1 | Hello | 45 | Hello4 |
| 3 | Luna | 78 | Luna5 |
| 4 | Feel good | 17 | Luna67 |
| 5 | My self | 23 | My self (r)|
+---------+---------------------------------------+
到目前为止,我创建了这个查询,但老实说,作为一个新手,我知道这一切都错了。它返回重复的行。我觉得我需要使用group by
和子查询,但经过 2 天的搜索和测试,我无法创建解决方案......我快疯了
样本数据 1
| work_id | work_name | recording_id | release_id | rec_name | year | month | day |
|---------|---------------------|--------------|------------|-----------------------------------------------------|------|-------|-----|
| 201 | Me ha dicho la luna | 253 | 5 | Me ha dicho la luna | 1998 | 4 | 22 |
| 201 | Me ha dicho la luna | 579 | 528 | Me ha dicho la luna (Moonlight Radio Edit) | 1998 | | |
| 201 | Me ha dicho la luna | 580 | 528 | Me ha dicho la luna (Luna llena Ambience Mix) | 1998 | | |
| 201 | Me ha dicho la luna | 581 | 528 | Me ha dicho la luna (Extended Callejuela's Version) | 1998 | | |
| 201 | Me ha dicho la luna | 582 | 528 | Me ha dicho la luna (Stoned Baby Free Version) | 1998 | | |
| 201 | Me ha dicho la luna | 252 | 1 | Me ha dicho la luna (con Chayanne) | 2006 | | |
样本数据 2
| work_id | work_name | recording_id | release_id | rec_name | year | month | day |
|---------|------------|--------------|------------|---------------------------------------------------------|------|-------|-----|
| 401 | Si amanece | 397 | 26 | Si amanece | 1978 | 7 | 1 |
| 401 | Si amanece | 634 | 309 | Si amanece | 1978 | 7 | 1 |
| 401 | Si amanece | 396 | 257 | Si amanece (con el Mariachi Oro y Plata de Pepe Chávez) | 1979 | | |
| 401 | Si amanece | 564 | 188 | Si amanece | 2001 | | |
| 401 | Si amanece | 394 | 213 | Si amanece | 2001 | | |
| 401 | Si amanece | 395 | 1 | Si amanece | 2006 | | |
| 401 | Si amanece | 638 | 295 | Si amanece | | | |
解决方案
这是为您的示例数据生成预期结果的查询:
select
w.work_id,
w.name work_name,
r.recording_id,
r.name recording_name
from work w
inner join recording r
on r.recording_id = (
select r1.recording_id
from recording r1
inner join releases l1 on l1.release_id = r1.release_id
where r1.work_id = w.work_id and r1.is_art = 1 and r1.is_vid = 0
order by -l1.year desc, -l1.month desc, -l1.day desc, r1.release_id desc
limit 1
)
这通过将work
表与连接起来recording
,使用相关的子查询来选择正确的行。从您的示例数据和结果来看,您似乎希望null
在对行进行排序时将 s 放在首位:这不是 MySQL 中的默认行为,因此我们使用了一种技巧,即排序依据- <column_name> desc
(将null
s 放在首位,同时尊重升序种类)。
注意:release
是MySQL 中的保留字,所以我改为命名该表releases
(否则,您需要用反引号括起来)。
工作编号 | 工作名称 | 录音ID | 录音名称 ------: | :-------- | ------------: | :------------- 1 | 你好 | 45 | 你好4 3 | 露娜 | 78 | 月神5 5 | 我的自我 | 23 | 我的自己(r)
或者,如果您正在运行 MySQL 8.0,您可以使用row_number()
来识别正确的记录。根据您的数据集,这可能会或可能不会表现得更好:
select work_id, work_name, recording_id, recording_name
from (
select
w.work_id,
w.name work_name,
r.recording_id,
r.name recording_name,
row_number() over(
partition by r.work_id
order by -l.year desc, -l.month desc, -l.day desc, r.release_id desc
) rn
from work w
inner join recording r
on r.work_id = w.work_id
and r.is_art = 1
and r.is_vid = 0
inner join releases l
on l.release_id = r.release_id
) t
where rn = 1
DB Fiddle 上的演示(与上述结果相同)
推荐阅读
- c# - 为每种颜色创建图像的渐变
- javascript - WYSIHTML5 - 未填充文本输入
- position - aframe 获取光标位置并在该位置设置实体
- selenium-webdriver - Javascript 仪表 - 类中的 webdriverjs 执行钩子
- android - 如何在 Ubuntu 18 上运行的 Virtual Box 中为 Androidx86 8.1rc2 VM 启用蓝牙
- javascript - javascript - 导出默认类型
- github - 如何在不破坏分叉或 PR 的情况下将带有分叉的公共回购变成私人回购?
- excel - 如何从混合 Excel 单元格中提取带前导零的数字?
- terraform - 是否可以使用 terraform provider vsphere 克隆现有的 VM(不是模板)
- objective-c - iOS 允许原生 html5 播放器进入横向模式