MySQL - 如何在 JOIN 中使用相关子查询
MySQL - How to use a correlated subquery inside a JOIN
我有两个 table,Objects
和 Events
。
Objects
的结构如下:
ID | Password
-------------
0 | aaaa
1 | bbbb
事件的结构如下:
Object | Date | Type
--------------------------
0 | 2020-06-01 | 0
0 | 2020-06-02 | 1
我想实现的是:对于每个ID,获取关联的最后一个事件类型。在上面的示例中,对象 0
将关联到 1
,因为 1
是 2020-06-02
上最后一个事件的类型。此外,只要对象没有任何事件,就将 1
关联到它。
我尝试为每个对象排序事件,这样我就可以使用查询加入我的对象信息:
SELECT ID, IFNULL(e.Type, 1)
FROM objects o
LEFT JOIN (
SELECT e.Object, e.Date, e.Type
FROM events e
WHERE e.Object = o.ID
ORDER BY e.Date DESC
LIMIT 1
) AS e ON e.Object = o.ID
它不起作用,因为 o.ID
未知,但我真的想不出任何其他解决方案。因此我的问题是:如何在加入的 table?
的条件中使用外部 table 的属性
如有不明之处请告诉我,谢谢。
SELECT ID, IFNULL(e.Type, 1)
FROM objects o
LEFT JOIN (
SELECT e.Object, max(e.Date), e.Type
FROM events e
GROUP BY e.Date DESC
) AS e ON e.Object = o.ID
您可以尝试这样的操作:
SELECT o.id, max(e.date) AS date, e.type
FROM objects o
INNER JOIN events e ON(o.id = e.object)
GROUP BY o.id, e.type
ORDER BY e.date DESC;
输出
+------+------------+------+
| id | date | type |
+------+------------+------+
| 0 | 2020-06-02 | 1 |
| 0 | 2020-06-01 | 0 |
+------+------------+------+
希望对您有所帮助。
在 Events
中使用 NOT EXISTS
至 return 仅最后一行日期:
SELECT ID, IFNULL(e.Type, 1) Type
FROM Objects o
LEFT JOIN (
SELECT e.Object, e.Type
FROM Events e
WHERE NOT EXISTS (
SELECT 1 FROM Events
WHERE Object = e.Object AND Date > e.Date
)
) AS e ON e.Object = o.ID
或:
SELECT
o.ID,
IFNULL((SELECT e.Type FROM Events e WHERE e.Object = o.ID ORDER BY e.Date DESC LIMIT 1), 1) Type
FROM Objects o
参见demo。
结果:
> ID | Type
> -: | ---:
> 0 | 1
> 1 | 1
如果您使用的是版本 8 或更高版本,则可以使用 row_number() 函数计算出最后一行
select * from
(
select id,coalesce(type,1) type,coalesce(date,date(now())) as dt,
row_number() over (partition by o.id order by coalesce(date,date(now())) desc) rn
from objects o
left join events e on e.object = o.id
order by o.id,dt desc
) s
where rn = 1;
我有两个 table,Objects
和 Events
。
Objects
的结构如下:
ID | Password
-------------
0 | aaaa
1 | bbbb
事件的结构如下:
Object | Date | Type
--------------------------
0 | 2020-06-01 | 0
0 | 2020-06-02 | 1
我想实现的是:对于每个ID,获取关联的最后一个事件类型。在上面的示例中,对象 0
将关联到 1
,因为 1
是 2020-06-02
上最后一个事件的类型。此外,只要对象没有任何事件,就将 1
关联到它。
我尝试为每个对象排序事件,这样我就可以使用查询加入我的对象信息:
SELECT ID, IFNULL(e.Type, 1)
FROM objects o
LEFT JOIN (
SELECT e.Object, e.Date, e.Type
FROM events e
WHERE e.Object = o.ID
ORDER BY e.Date DESC
LIMIT 1
) AS e ON e.Object = o.ID
它不起作用,因为 o.ID
未知,但我真的想不出任何其他解决方案。因此我的问题是:如何在加入的 table?
如有不明之处请告诉我,谢谢。
SELECT ID, IFNULL(e.Type, 1)
FROM objects o
LEFT JOIN (
SELECT e.Object, max(e.Date), e.Type
FROM events e
GROUP BY e.Date DESC
) AS e ON e.Object = o.ID
您可以尝试这样的操作:
SELECT o.id, max(e.date) AS date, e.type
FROM objects o
INNER JOIN events e ON(o.id = e.object)
GROUP BY o.id, e.type
ORDER BY e.date DESC;
输出
+------+------------+------+
| id | date | type |
+------+------------+------+
| 0 | 2020-06-02 | 1 |
| 0 | 2020-06-01 | 0 |
+------+------------+------+
希望对您有所帮助。
在 Events
中使用 NOT EXISTS
至 return 仅最后一行日期:
SELECT ID, IFNULL(e.Type, 1) Type
FROM Objects o
LEFT JOIN (
SELECT e.Object, e.Type
FROM Events e
WHERE NOT EXISTS (
SELECT 1 FROM Events
WHERE Object = e.Object AND Date > e.Date
)
) AS e ON e.Object = o.ID
或:
SELECT
o.ID,
IFNULL((SELECT e.Type FROM Events e WHERE e.Object = o.ID ORDER BY e.Date DESC LIMIT 1), 1) Type
FROM Objects o
参见demo。
结果:
> ID | Type
> -: | ---:
> 0 | 1
> 1 | 1
如果您使用的是版本 8 或更高版本,则可以使用 row_number() 函数计算出最后一行
select * from
(
select id,coalesce(type,1) type,coalesce(date,date(now())) as dt,
row_number() over (partition by o.id order by coalesce(date,date(now())) desc) rn
from objects o
left join events e on e.object = o.id
order by o.id,dt desc
) s
where rn = 1;