LEFT JOIN two MySql tables while second table order by desc and limit to 1
LEFT JOIN two MySql tables while second table order by desc and limit to 1
我有如下两个表格
NA_table
+----+-------+-------+---------------+---------------------+-----+
| id | nname | phone | nip | ntime | iid |
+----+-------+-------+---------------+---------------------+-----+
| 1 | john | +xxxx | 192.168.1.10 | 2020-04-21 11:10:10 | 23 |
| 2 | bill | +xxxx | 192.168.1.11 | 2020-04-21 12:10:10 | 44 |
| 3 | husky | +xxxx | 192.168.1.12 | 2020-04-21 13:10:10 | 44 |
| 4 | lab | +xxxx | 192.168.1.13 | 2020-04-21 14:10:10 | 33 |
| 5 | bill | +xxxx | 192.168.1.12 | 2020-04-21 11:10:15 | 44 |
| 6 | cal | +xxxx | 192.168.1.13 | 2020-04-21 16:10:10 | 12 |
| 7 | jess | +xxxx | 192.168.1.11 | 2020-04-21 17:10:10 | 90 |
| 8 | minn | +xxxx | 192.168.1.12 | 2020-04-21 18:10:10 | 44 |
| 9 | jess | +xxxx | 192.168.1.11 | 2020-04-21 17:10:10 | 21 |
+----+-------+-------+---------------+---------------------+-----+
CD_table
+----+--------------+---------------------+-------+
| cid | cip | ctime | other |
+----+--------------+---------------------+-------+
| 1 | 192.168.1.11 | 2020-04-21 03:22:19 | text |
| 2 | 192.168.1.12 | 2020-04-21 03:10:10 | text |
| 3 | 192.168.1.11 | 2020-04-21 06:11:12 | text |
| 4 | 192.168.1.19 | 2020-04-21 06:10:03 | text |
| 5 | 192.168.1.22 | 2020-04-21 13:10:10 | text |
| 6 | 192.168.1.11 | 2020-04-21 14:14:17 | text |
| 7 | 192.168.1.12 | 2020-04-21 16:09:10 | text |
| 8 | 192.168.1.11 | 2020-04-22 09:07:11 | text |
+----+--------------+---------------------+-------+
使用这两个表我想运行这个查询
SELECT
CD_table.ctime AS CTIME,
CD_table.cip AS CIP,
CD_table.other AS OTHER,
NA_table.phone AS PHONE,
FROM NA_table
LEFT JOIN CD_table
ON NA_table.nip = CD_table.cip
WHERE
NA_table.NAIID = '44'
AND
NA_table.ntime between '2020-04-21 11:10:00' AND '2020-04-21 11:10:59'
AND
CD_table.ctime between '2020-04-21 00:10:00' AND '2020-04-21 23:59:59'
这给了我这个结果。
+----------------------+---------------+-------+-------+
| CTIME | CIP | OTHER | PHONE |
+----------------------+---------------+-------+-------+
| 2020-04-21 03:22:19 | 192.168.1.11 | text | +xxxx |
| 2020-04-21 03:10:10 | 192.168.1.12 | text | +xxxx |
| 2020-04-21 06:11:12 | 192.168.1.11 | text | +xxxx |
| 2020-04-21 14:14:17 | 192.168.1.11 | text | +xxxx |
| 2020-04-21 16:09:10 | 192.168.1.12 | text | +xxxx |
+----------------------+---------------+-------+-------+
但我希望我的输出按 CTIME 排序,并且只打印每个 CD_table 记录的最后一个匹配记录,如下所示
+---------------------+---------------+-------+-------+
| CTIME | CIP | OTHER | phone |
+---------------------+---------------+-------+-------+
| 2020-04-21 14:14:17 | 192.168.1.11 | text | +xxxx |
| 2020-04-21 16:09:10 | 192.168.1.12 | text | +xxxx |
+---------------------+---------------+-------+-------+
我可以在何处对查询执行 DESC 和 LIMIT 部分。或者还有其他方法可以拆分我的查询。
您可以使用子查询过滤 cd_table
给定时间间隔内的最新记录。
此外,由于您的查询没有 return 来自 na_table
的任何内容,我将连接转换为 exists
条件 - 这通常在这种情况下更有效。
select c.ctime, c.cip, c.other
from cd_table c
where
c.ctime = (
select max(c1.ctime)
from cd_table c1
where
c1.cip = c.cip
and c1.ctime >= '2020-04-21 00:10:00'
and c1.ctime < '2020-04-22'
)
and exists (
select 1
from na_table n
where
n.nip = c.cip
and n.naid = 44
and n.ntime >= '2020-04-21 11:10:00'
and n.ntime < '2020-04-21 11:11:00'
)
请注意,我重写了日期条件以使用半开间隔(这避免了每次都处理尾随 59 秒)。
对于性能,请考虑以下指标:
cd_table(cip, ctime)
na_table(nip, naid, time)
将 other
添加到 cd_table
上的索引可能会带来额外的提升。
如果您使用 MySQL 8.0
那么您可以使用 row_number()
SELECT
CTIME,
CIP,
OTHER
from
(
SELECT
CD_table.ctime AS CTIME,
CD_table.cip AS CIP,
CD_table.other AS OTHER
row_number() over (order by CTIME desc) as rnk
FROM NA_table
LEFT JOIN CD_table
ON NA_table.nip = CD_table.cip
WHERE
NA_table.NAIID = '44'
AND
NA_table.ntime between '2020-04-21 11:10:00' AND '2020-04-21 11:10:59'
AND
CD_table.ctime between '2020-04-21 00:10:00' AND '2020-04-21 23:59:59'
) val
where rnk = 1
order by
CTIME
我有如下两个表格
NA_table
+----+-------+-------+---------------+---------------------+-----+
| id | nname | phone | nip | ntime | iid |
+----+-------+-------+---------------+---------------------+-----+
| 1 | john | +xxxx | 192.168.1.10 | 2020-04-21 11:10:10 | 23 |
| 2 | bill | +xxxx | 192.168.1.11 | 2020-04-21 12:10:10 | 44 |
| 3 | husky | +xxxx | 192.168.1.12 | 2020-04-21 13:10:10 | 44 |
| 4 | lab | +xxxx | 192.168.1.13 | 2020-04-21 14:10:10 | 33 |
| 5 | bill | +xxxx | 192.168.1.12 | 2020-04-21 11:10:15 | 44 |
| 6 | cal | +xxxx | 192.168.1.13 | 2020-04-21 16:10:10 | 12 |
| 7 | jess | +xxxx | 192.168.1.11 | 2020-04-21 17:10:10 | 90 |
| 8 | minn | +xxxx | 192.168.1.12 | 2020-04-21 18:10:10 | 44 |
| 9 | jess | +xxxx | 192.168.1.11 | 2020-04-21 17:10:10 | 21 |
+----+-------+-------+---------------+---------------------+-----+
CD_table
+----+--------------+---------------------+-------+
| cid | cip | ctime | other |
+----+--------------+---------------------+-------+
| 1 | 192.168.1.11 | 2020-04-21 03:22:19 | text |
| 2 | 192.168.1.12 | 2020-04-21 03:10:10 | text |
| 3 | 192.168.1.11 | 2020-04-21 06:11:12 | text |
| 4 | 192.168.1.19 | 2020-04-21 06:10:03 | text |
| 5 | 192.168.1.22 | 2020-04-21 13:10:10 | text |
| 6 | 192.168.1.11 | 2020-04-21 14:14:17 | text |
| 7 | 192.168.1.12 | 2020-04-21 16:09:10 | text |
| 8 | 192.168.1.11 | 2020-04-22 09:07:11 | text |
+----+--------------+---------------------+-------+
使用这两个表我想运行这个查询
SELECT
CD_table.ctime AS CTIME,
CD_table.cip AS CIP,
CD_table.other AS OTHER,
NA_table.phone AS PHONE,
FROM NA_table
LEFT JOIN CD_table
ON NA_table.nip = CD_table.cip
WHERE
NA_table.NAIID = '44'
AND
NA_table.ntime between '2020-04-21 11:10:00' AND '2020-04-21 11:10:59'
AND
CD_table.ctime between '2020-04-21 00:10:00' AND '2020-04-21 23:59:59'
这给了我这个结果。
+----------------------+---------------+-------+-------+
| CTIME | CIP | OTHER | PHONE |
+----------------------+---------------+-------+-------+
| 2020-04-21 03:22:19 | 192.168.1.11 | text | +xxxx |
| 2020-04-21 03:10:10 | 192.168.1.12 | text | +xxxx |
| 2020-04-21 06:11:12 | 192.168.1.11 | text | +xxxx |
| 2020-04-21 14:14:17 | 192.168.1.11 | text | +xxxx |
| 2020-04-21 16:09:10 | 192.168.1.12 | text | +xxxx |
+----------------------+---------------+-------+-------+
但我希望我的输出按 CTIME 排序,并且只打印每个 CD_table 记录的最后一个匹配记录,如下所示
+---------------------+---------------+-------+-------+
| CTIME | CIP | OTHER | phone |
+---------------------+---------------+-------+-------+
| 2020-04-21 14:14:17 | 192.168.1.11 | text | +xxxx |
| 2020-04-21 16:09:10 | 192.168.1.12 | text | +xxxx |
+---------------------+---------------+-------+-------+
我可以在何处对查询执行 DESC 和 LIMIT 部分。或者还有其他方法可以拆分我的查询。
您可以使用子查询过滤 cd_table
给定时间间隔内的最新记录。
此外,由于您的查询没有 return 来自 na_table
的任何内容,我将连接转换为 exists
条件 - 这通常在这种情况下更有效。
select c.ctime, c.cip, c.other
from cd_table c
where
c.ctime = (
select max(c1.ctime)
from cd_table c1
where
c1.cip = c.cip
and c1.ctime >= '2020-04-21 00:10:00'
and c1.ctime < '2020-04-22'
)
and exists (
select 1
from na_table n
where
n.nip = c.cip
and n.naid = 44
and n.ntime >= '2020-04-21 11:10:00'
and n.ntime < '2020-04-21 11:11:00'
)
请注意,我重写了日期条件以使用半开间隔(这避免了每次都处理尾随 59 秒)。
对于性能,请考虑以下指标:
cd_table(cip, ctime)
na_table(nip, naid, time)
将 other
添加到 cd_table
上的索引可能会带来额外的提升。
如果您使用 MySQL 8.0
那么您可以使用 row_number()
SELECT
CTIME,
CIP,
OTHER
from
(
SELECT
CD_table.ctime AS CTIME,
CD_table.cip AS CIP,
CD_table.other AS OTHER
row_number() over (order by CTIME desc) as rnk
FROM NA_table
LEFT JOIN CD_table
ON NA_table.nip = CD_table.cip
WHERE
NA_table.NAIID = '44'
AND
NA_table.ntime between '2020-04-21 11:10:00' AND '2020-04-21 11:10:59'
AND
CD_table.ctime between '2020-04-21 00:10:00' AND '2020-04-21 23:59:59'
) val
where rnk = 1
order by
CTIME