MySQL 分组排序
MySQL grouping and sorting
mysql> describe jobs;
+--------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+----------------+
| job_id | int(11) | NO | PRI | NULL | auto_increment |
| candidate_id | int(11) | NO | MUL | NULL | |
| company_id | int(11) | NO | MUL | NULL | |
| start_date | date | NO | MUL | NULL | |
| end_date | date | NO | MUL | NULL | |
+--------------+---------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
每个候选人可以有多个职位。我想为每个候选人找到最新的工作(基于开始日期,因为结束日期可以是 0000-00-00),并检查(在 PHP 中)如果 end_Date 不是 0000-00 -00.
(如果您的最后结束日期不是 0000-00-00,那么您目前处于失业状态,这正是我要找的;我不知道如何在我的查询中执行此操作,所以会这样做在 PHP).
查询 SELECT candidate_id, end_Date FROM jobs ORDER BY candidate_id , start_date DESC
让我完成了一半。
+--------------+------------+
| candidate_id | end_Date |
+--------------+------------+
| 1 | 2019-08-31 |
| 1 | 2019-01-31 |
| 1 | 2019-05-31 |
| 2 | 0000-00-00 |
| 2 | 2018-02-28 |
| 2 | 2017-05-31 |
| 2 | 2016-09-30 |
| 3 | 0000-00-00 |
| 3 | 2019-05-31 |
| 4 | 2019-04-30 |
| 4 | 2019-09-30 |
(如何)我只能得到每个候选人 ID 的第一个条目(最近 start_date
的行)?我可以只获得结束日期不是 0000-00-00 的那些吗?
(哎呀,看来我通过 end_date 的订单不起作用)
您可以使用相关子查询进行过滤:
select j.*
from jobs j
where j.start_date = (
select max(start_date)
from jobs j1
where j1.candidate_id = j.candidate_id and j1.end_date <> '0000-00-00'
)
子查询 returns 最大的 start_date
其 end_date
不是当前候选的 null
。
另一种解决每组前 1 名问题的典型方法是使用 anti
-左连接:
select j.*
from jobs j
left join jobs j1
on j1.candidate_id = j.candidate_id
and j1.start_date > j.start_date
and j1.end_date is not null
where
j.end_date is not null
and j1.job_id is null
这句话是:给我一个非null
end_date
的记录,没有其他记录存在相同的candidate_id
,更大的start_date
和非null
end_date
.
您可以在最大 start_date 组中按候选人
使用联接
select *
from jobs j
inner join (
select candidate_id , max(start_date) max_start_date
from jobs
group by candidate_id
) t on t.candidate_id = j.candidate_id
and t.max_start_date = j.start_date
没有子查询的选项:
SELECT
j.*
FROM
jobs AS j
LEFT JOIN jobs AS j2 ON (
j2.candidate_id = j.candidate_id
AND j2.start_date > j.start.date
)
WHERE
j2.candidate_id IS NULL
您想使用复合索引(candidate_id、start_date)来优化查询。
您可以通过聚合来做到这一点:
select candidate_id,
(case when sum(end_date = '0000-00-00') > 0
then '0000-00-00'
else max(end_date)
end) as enddate
from jobs j
group by candidate_id;
或另一种方法:
select j.*
from jobs j
where j.end_date = '0000-00-00' or
(not exists (select 1
from jobs j2
where j2.candidate_id = j.candidate_id and
(j2.end_date = '0000-00-00' or
j2.end_date > j.end_date
)
)
);
甚至:
select j.*
from jobs j
where j.job_id = (select j2.job_id
from jobs j2
where j2.candidate_id = j.candidate_id
order by (j2.end_date = '0000-00-00') desc,
j2.end_date desc
);
mysql> describe jobs;
+--------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+----------------+
| job_id | int(11) | NO | PRI | NULL | auto_increment |
| candidate_id | int(11) | NO | MUL | NULL | |
| company_id | int(11) | NO | MUL | NULL | |
| start_date | date | NO | MUL | NULL | |
| end_date | date | NO | MUL | NULL | |
+--------------+---------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
每个候选人可以有多个职位。我想为每个候选人找到最新的工作(基于开始日期,因为结束日期可以是 0000-00-00),并检查(在 PHP 中)如果 end_Date 不是 0000-00 -00.
(如果您的最后结束日期不是 0000-00-00,那么您目前处于失业状态,这正是我要找的;我不知道如何在我的查询中执行此操作,所以会这样做在 PHP).
查询 SELECT candidate_id, end_Date FROM jobs ORDER BY candidate_id , start_date DESC
让我完成了一半。
+--------------+------------+
| candidate_id | end_Date |
+--------------+------------+
| 1 | 2019-08-31 |
| 1 | 2019-01-31 |
| 1 | 2019-05-31 |
| 2 | 0000-00-00 |
| 2 | 2018-02-28 |
| 2 | 2017-05-31 |
| 2 | 2016-09-30 |
| 3 | 0000-00-00 |
| 3 | 2019-05-31 |
| 4 | 2019-04-30 |
| 4 | 2019-09-30 |
(如何)我只能得到每个候选人 ID 的第一个条目(最近 start_date
的行)?我可以只获得结束日期不是 0000-00-00 的那些吗?
(哎呀,看来我通过 end_date 的订单不起作用)
您可以使用相关子查询进行过滤:
select j.*
from jobs j
where j.start_date = (
select max(start_date)
from jobs j1
where j1.candidate_id = j.candidate_id and j1.end_date <> '0000-00-00'
)
子查询 returns 最大的 start_date
其 end_date
不是当前候选的 null
。
另一种解决每组前 1 名问题的典型方法是使用 anti
-左连接:
select j.*
from jobs j
left join jobs j1
on j1.candidate_id = j.candidate_id
and j1.start_date > j.start_date
and j1.end_date is not null
where
j.end_date is not null
and j1.job_id is null
这句话是:给我一个非null
end_date
的记录,没有其他记录存在相同的candidate_id
,更大的start_date
和非null
end_date
.
您可以在最大 start_date 组中按候选人
使用联接select *
from jobs j
inner join (
select candidate_id , max(start_date) max_start_date
from jobs
group by candidate_id
) t on t.candidate_id = j.candidate_id
and t.max_start_date = j.start_date
没有子查询的选项:
SELECT
j.*
FROM
jobs AS j
LEFT JOIN jobs AS j2 ON (
j2.candidate_id = j.candidate_id
AND j2.start_date > j.start.date
)
WHERE
j2.candidate_id IS NULL
您想使用复合索引(candidate_id、start_date)来优化查询。
您可以通过聚合来做到这一点:
select candidate_id,
(case when sum(end_date = '0000-00-00') > 0
then '0000-00-00'
else max(end_date)
end) as enddate
from jobs j
group by candidate_id;
或另一种方法:
select j.*
from jobs j
where j.end_date = '0000-00-00' or
(not exists (select 1
from jobs j2
where j2.candidate_id = j.candidate_id and
(j2.end_date = '0000-00-00' or
j2.end_date > j.end_date
)
)
);
甚至:
select j.*
from jobs j
where j.job_id = (select j2.job_id
from jobs j2
where j2.candidate_id = j.candidate_id
order by (j2.end_date = '0000-00-00') desc,
j2.end_date desc
);