sql - 在一对多关系中,根据 MIN 值返回不同的行

标签 sql postgresql one-to-many greatest-n-per-group

假设一位患者进行了多次就诊。我想编写一个查询,根据他们最早的访问返回不同的患者行。例如,考虑以下行。

patients
-------------
id    name
1     Bob
2     Jim
3     Mary

visits
-------------
id    patient_id    visit_date    reference_number
1     1             6/29/14       09f3be26
2     1             7/8/14        34c23a9e
3     2             7/10/14       448dd90a

我想看到查询返回的是:

id    name    first_visit_date    reference_number
1     Bob     6/29/14             09f3be26
2     Jim     7/10/14             448dd90a

我试过的看起来像:

SELECT
  patients.id, 
  patients.name, 
  visits.visit_date AS first_visit_date, 
  visits.reference_number
FROM
  patients
INNER JOIN (
  SELECT
    *
  FROM
    visits
  ORDER BY
    visit_date
  LIMIT
    1
) visits ON
  visits.patient_id = patients.id

添加 LIMIT 会导致查询返回 0 行,但删除它会导致查询返回重复项。这里有什么诀窍?我也试过在 INNER JOIN 中选择 MIN(visit_date) 但这也返回了 dups。

更新

有人建议这个问题是重复的,但对我来说似乎不同,因为我是在两个单独的表上做这个的。在另一个问题上接受的答案建议在 y.max_total = x.total 上加入,如果要加入的表是从中选择的同一个表,则该方法有效。此外,我需要返回具有 MIN 日期的行中的其他列,而不仅仅是日期本身。

不过,我接受的答案效果很好。

最佳答案

避免 DISTINCT ON(p.id),而是使用普通的旧 NOT EXISTS(...) 代替

SELECT p.id, p.name
     , v.first_visit_date, v.reference_number
FROM patients p
JOIN visits v ON p.id = v.patient_id
    -- exclude all join-products that are not the first for a patient.
WHERE NOT EXISTS (
   SELECT *
   FROM visits nx
   WHERE nx.patient_id = v.patient_id
   AND ( nx.visit_date < v.visit_date
       OR (nx.visit_date = v.visit_date AND nx.id < v.id) -- tie-breaker condition
       )
   );  

关于sql - 在一对多关系中,根据 MIN 值返回不同的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25551344/

相关文章:

mysql - 如何从我的 MySQL 表中删除相似的行?

python - 连接两个表,文件名具有额外的字符串,正则表达式从文件名中删除字符串并进行连接

mysql - 如何从 MySQL 表中的多个列中获取指定最小长度的所有不同单词?

Android:每个表的ContentProvider/处理一对多关系

sql - 带 Where 子句的 OFFSET SQL 查询

sql - 如何按条件计算计数

sql - 使用 1 个带 3 个外键的联结表或 2 个共享排序的联结表?

sql - 如何排除对称记录

Mysql 一对多连接,行到列

grails - 如何执行单向一对多关系?