MySQL为每个用户显示多个数据

ivqmmu1c  于 2023-03-22  发布在  Mysql
关注(0)|答案(2)|浏览(122)

我有表:
t_patients(id为auto_increment)
| 身份证|患者编号|创建时间|
| - ------|- ------|- ------|
| 1个|一百|2023年1月10日|
| 第二章|二百|2023年1月11日|
| 三个|一百|2023年1月15日|
结果需要这样:
| 患者编号|第一次来|第二次来|第三次来|
| - ------|- ------|- ------|- ------|
| 一百|2023年1月10日|2023年1月15日|x|
| 二百|2023年1月11日|x|x|
我已经在谷歌上搜索过了,但是仍然没有找到所需的确切输出。SQL应该是什么查询?

uxhixvfz

uxhixvfz1#

你可以使用mysql中的COALESCE函数和条件聚合来实现这一点。
MySQL的COALESCE()函数用于返回表达式列表中的第一个非空值。如果列表中的所有值都为NULL,则COALESCE()函数返回NULL。
这里是a demo using DBFIDDLE
以下查询将为您提供预期输出:

SELECT 
  patient_id,
  COALESCE(MAX(IF(rn = 1, created_at, NULL)), 'x') AS `1st come`,
  COALESCE(MAX(IF(rn = 2, created_at, NULL)), 'x') AS `2nd come`,
  COALESCE(MAX(IF(rn = 3, created_at, NULL)), 'x') AS `3rd come`
FROM (
  SELECT 
    id,
    patient_id,
    created_at,
    ROW_NUMBER() OVER (PARTITION BY patient_id ORDER BY created_at) AS rn
  FROM t_patients
) AS t
GROUP BY patient_id;

输出:
| 患者编号|第一次来|第二次来|第三次来|
| - ------|- ------|- ------|- ------|
| 一百|2023年1月10日|2023年1月15日|x|
| 二百|2023年1月11日|x|x|

yh2wf1be

yh2wf1be2#

我写了一个不使用窗口函数的查询(因为MySQL 5.7及以下版本不支持窗口函数)。为了让事情更有趣,让我们添加几行:

create table t_patients (id int primary key auto_increment,patient_id int,create_at date);
insert t_patients values(default,100,'2023-01-10'),
(default,200,'2023-01-11'),
(default,100,'2023-01-15'),
(default,300,'2023-01-15'),
(default,200,'2023-01-16'),
(default,100,'2023-01-16'),
(default,300,'2023-01-17'),
(default,300,'2023-01-18');

select * from t_patients;
+----+------------+------------+
| id | patient_id | create_at  |
+----+------------+------------+
|  1 |        100 | 2023-01-10 |
|  2 |        200 | 2023-01-11 |
|  3 |        100 | 2023-01-15 |
|  4 |        300 | 2023-01-15 |
|  5 |        200 | 2023-01-16 |
|  6 |        100 | 2023-01-16 |
|  7 |        300 | 2023-01-17 |
|  8 |        300 | 2023-01-18 |
+----+------------+------------+

之后,让我们编写一个查询,根据每个患者的create_at值排列每个patient_id。为每个患者的create_at值指定一个row_id,从1开始。注意,每当patient_id更改时,row_id值应重置为1,因此每个patient_id都可以从1开始。

select patient_id,create_at , 
case @pid when patient_id then  @row_id:=@row_id+1 else  @row_id:=1 end as row_id ,
case when @pid!=patient_id then @pid:=patient_id else @pid end as track_pid -- the track_pid serves to keep the @pid value up to date 
from
t_patients,
(select @row_id:=0,@pid:=(select max(patient_id) from t_patients) ) t
order by patient_id , create_at
;
+------------+------------+--------+-----------+
| patient_id | create_at  | row_id | track_pid |
+------------+------------+--------+-----------+
|        100 | 2023-01-10 |      1 |       100 |
|        100 | 2023-01-15 |      2 |       100 |
|        100 | 2023-01-16 |      3 |       100 |
|        200 | 2023-01-11 |      1 |       200 |
|        200 | 2023-01-16 |      2 |       200 |
|        300 | 2023-01-15 |      1 |       300 |
|        300 | 2023-01-17 |      2 |       300 |
|        300 | 2023-01-18 |      3 |       300 |
+------------+------------+--------+-----------+

然后,上面的查询被用作我们的主查询的派生表(别名为tb),它执行表透视工作。这里我决定使用min()函数,而不是使用coalesce函数,因为在ascii中,数字作为字符串出现在字母之前,所以当create_at值存在时,min()将选择create_at而不是字母x

select patient_id,
min(case when row_id=1 then create_at else 'x' end) 1st,
min(case when row_id=2 then create_at else 'x' end) 2nd,
min(case when row_id=3 then create_at else 'x' end) 3rd,
min(case when row_id=4 then create_at else 'x' end) 4th
from
    (select patient_id,create_at , 
    case @pid when patient_id then  @row_id:=@row_id+1 else  @row_id:=1 end as row_id ,
    case when @pid!=patient_id then @pid:=patient_id else @pid end as track_pid
    from
    t_patients,(select @row_id:=0,@pid:=(select max(patient_id) from t_patients) ) t
    order by patient_id , create_at) tb
group by patient_id
order by patient_id
;

+------------+------------+------------+------------+------+
| patient_id | 1st        | 2nd        | 3rd        | 4th  |
+------------+------------+------------+------------+------+
|        100 | 2023-01-10 | 2023-01-15 | 2023-01-16 | x    |
|        200 | 2023-01-11 | 2023-01-16 | x          | x    |
|        300 | 2023-01-15 | 2023-01-17 | 2023-01-18 | x    |
+------------+------------+------------+------------+------+

相关问题