关于mysql:SQL从两个具有内部连接和限制的表中进行选择

SQL Selecting from two Tables with inner join and limit

本问题已经有最佳答案,请猛点这里访问。

我有两个表ServiceStatus。 服务表仅包含nameid

1
2
3
4
| id |  name |
|----|-------|
|  1 | Test1 |
|  2 | Test2 |

和像这样的状态表

1
2
3
4
5
6
| id | status | service_id |                 timestamp |
|----|--------|------------|---------------------------|
|  1 |     OK |          1 | October, 15 2015 09:03:07 |
|  2 |     OK |          1 | October, 15 2015 09:08:07 |
|  3 |     OK |          2 | October, 15 2015 10:05:23 |
|  4 |     OK |          2 | October, 15 2015 10:15:23 |

我想得到这样的数据

1
2
3
4
| id |  name | status |                 timestamp |
|----|-------|--------|---------------------------|
|  1 | Test1 |     OK | October, 15 2015 09:08:07 |
|  2 | Test2 |     OK | October, 15 2015 10:15:23 |

服务数据的最新状态。 我试过这个说法

1
2
3
4
5
6
SELECT ser.id, ser.name, a.status, a.timestamp
from Service ser
  inner join (select * from status
              order by Status.timestamp
              DESC limit 1) as a
    on a.service_id = ser.id

但我只能得到

1
2
3
| id |  name | status |                 timestamp |
|----|-------|--------|---------------------------|
|  2 | Test2 |     OK | October, 15 2015 10:15:23 |

如何更改语句以获得我想要的内容?

用于测试SQL Fiddle


对于每个服务,仅当不存在以后的服务时,使用NOT EXISTS返回状态:

1
2
3
4
5
6
select ser.id, ser.name, st.status, st.timestamp
from service ser
  left join status st1 on ser.id = st1.service_id
where not exists (select 1 from status st2
                  where st2.service_id = st1.service_id
                    and st2.timestamp > st1.timestamp)

(可选)执行LEFT JOIN以返回没有任何状态的服务。 如果不需要,请切换到JOIN


你可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT
  ser.id,
  ser.name,
  s.status,
  s.timestamp
FROM Service ser
INNER JOIN status as s ON s.service_id = ser.id
INNER JOIN
(
   SELECT
     service_id,
     MAX(timestamp) AS MaxDate
   FROM status
   GROUP BY service_id
) AS a  ON a.service_id = s.service_id
       AND a.MaxDate = s.timestamp;

与子查询的连接:

1
2
3
4
5
SELECT
  service_id,
  MAX(timestamp) AS MaxDate
FROM status
GROUP BY service_id

将消除除最新日期之外的所有状态。


您可以使用此查询获得结果

1
2
3
4
5
6
7
8
9
SELECT MAX(s.id),
  sr.id,
  sr.name,
  s.status,
  s.timestamp
FROM Service AS sr
INNER JOIN status AS s ON s.service_id = sr.id
GROUP BY sr.id
ORDER BY s.id ASC

我认为这对你有用


您可以在没有这样的子查询的情况下获得该结果

1
2
3
4
5
6
7
SELECT s.id, s.name,
SUBSTRING_INDEX(GROUP_CONCAT(st.status ORDER BY st.timestamp DESC),',',1) AS status_value,
SUBSTRING_INDEX(GROUP_CONCAT(st.timestamp ORDER BY st.timestamp DESC),',',1) AS time_stamp
FROM Service s
JOIN Status st ON(st.service_id = s.id)
GROUP BY s.id
ORDER BY s.id

输出是

1
2
3
id  name    status_value    time_stamp
1   Test1   OK            2015-10-15 09:08:07
2   Test2   OK            2015-10-15 10:15:23

试试这个...

1
2
3
4
5
6
SELECT ser.id, ser.name, a.status, a.max_timesatmp_rm
from Service ser
  inner join (select *,row_number() over (partiton by service_id  order by timestamp  desc ) as max_timesatmp_rm from status
              ) as a
    on a.service_id = ser.id
    where a.max_timesatmp_rm=1;