SQL:如何检索一对多关系中的最新关联

huangapple go评论70阅读模式
英文:

SQL: How to Retrieve the Most Recent Association in a One-To-Many Relationship

问题

以下是存储一对多关系的表格,其中一个用户可能与一个或多个配置文件相关联:

+----+---------+------------+------------------------+
| ID | USER_ID | PROFILE_ID | LAST_PROFILE_DATE_TIME |
+----+---------+------------+------------------------+
|  1 |     100 |        101 | 04.06.23 08:35:19.5393 |
|  2 |     100 |        102 | 05.06.23 08:35:19.5393 |
+----+---------+------------+------------------------+

如何获取用户 100 的最新配置文件?以下是预期结果:

+------------+
| PROFILE_ID |
+------------+
|        102 |
+------------+

我需要一个单一的值,用于更新另一个表中的字段。

这是我的尝试...但问题是我得到了两行,因为GROUP BY子句需要所有字段,而不是MAX

SELECT up.PROFILE_ID
FROM
  (SELECT USER_ID, PROFILE_ID, MAX(LAST_PROFILE_DATE_TIME)
     FROM USER_PROFILE
    GROUP BY USER_ID, PROFILE_ID) up
WHERE up.USER_ID = 100;

我需要在Oracle和PostgreSQL上运行此查询。非常感谢您的帮助。

英文:

Here below is a table that stores a one-to-many relationship where one user might be associated with one or more profiles:

+----+---------+------------+------------------------+
| ID | USER_ID | PROFILE_ID | LAST_PROFILE_DATE_TIME |
+----+---------+------------+------------------------+
|  1 |     100 |        101 | 04.06.23 08:35:19.5393 |
|  2 |     100 |        102 | 05.06.23 08:35:19.5393 |
+----+---------+------------+------------------------+

How do I get the latest profile for user 100? Here's the expected result:

+------------+
| PROFILE_ID |
+------------+
|        102 |
+------------+

I need a single value to be used to update a field in another table.

This is my attempt... but the problem is that I get two rows because the GROUP BY clause requires all the fields but MAX:

SELECT up.PROFILE_ID
FROM
  (SELECT USER_ID, PROFILE_ID, MAX(LAST_PROFILE_DATE_TIME)
     FROM USER_PROFILE
    GROUP BY USER_ID, PROFILE_ID) up
WHERE up.USER_ID = 100;

I need to run the query on both Oracle and PostgreSQL. Any help would be really appreciated.

答案1

得分: 2

你可以按照以下方式执行:

首先获取每个USER_ID的最新LAST_PROFILE_DATE_TIME:

select USER_ID, max(LAST_PROFILE_DATE_TIME) as MAX_LAST_PROFILE_DATE_TIME
from USER_PROFILE
where USER_ID = 100
group by USER_ID

然后将这个数据集与你的表连接以获取PROFILE_ID:

select t.PROFILE_ID
from USER_PROFILE t
inner join (
  select USER_ID, max(LAST_PROFILE_DATE_TIME) as MAX_LAST_PROFILE_DATE_TIME
  from USER_PROFILE
  where USER_ID = 100
  group by USER_ID
) as s on s.USER_ID = t.USER_ID and s.MAX_LAST_PROFILE_DATE_TIME = t.LAST_PROFILE_DATE_TIME;
英文:

You can do it as follows :

First get the latest LAST_PROFILE_DATE_TIME per USER_ID :

  select USER_ID, max(LAST_PROFILE_DATE_TIME) as MAX_LAST_PROFILE_DATE_TIME
  from USER_PROFILE
  where USER_ID = 100
  group by USER_ID

Then join this dataset to your table to obtain PROFILE_ID:

select t.PROFILE_ID
from USER_PROFILE t
inner join (
  select USER_ID, max(LAST_PROFILE_DATE_TIME) as MAX_LAST_PROFILE_DATE_TIME
  from USER_PROFILE
  where USER_ID = 100
  group by USER_ID
) as s on s.USER_ID = t.USER_ID and s.MAX_LAST_PROFILE_DATE_TIME = t.LAST_PROFILE_DATE_TIME;

答案2

得分: 2

以下是翻译好的部分:

你可以使用 ROW_NUMBER 分析函数:

SELECT profile_id,
       last_profile_date_time
FROM   (
  SELECT profile_id,
         last_profile_date_time,
         ROW_NUMBER()
           OVER (ORDER BY last_profile_date_time DESC) AS rn
  FROM   table_name
  WHERE  user_id = 100
  ORDER BY last_profile_date_time DESC
) q
WHERE  RN = 1;

或者两种数据库都支持 FETCH FIRST ROW ONLY 语法:

SELECT profile_id,
       last_profile_date_time
FROM   table_name
WHERE  user_id = 100
ORDER BY last_profile_date_time DESC
FETCH FIRST ROW ONLY;

对于示例数据:

CREATE TABLE table_name (
  ID         INT,
  USER_ID    INT,
  PROFILE_ID INT,
  LAST_PROFILE_DATE_TIME TIMESTAMP
);

INSERT INTO table_name (id, user_id, profile_id, last_profile_date_time)
  VALUES (1, 100, 101, TIMESTAMP '2023-06-04 08:35:19.5393' );
INSERT INTO table_name (id, user_id, profile_id, last_profile_date_time)
  VALUES (2, 100, 102, TIMESTAMP '2023-06-05 08:35:19.5393' );

两者的输出结果均为:

profile_id last_profile_date_time
102 2023-06-05 08:35:19.5393

PostgreSQL fiddle Oracle fiddle

英文:

You can use the ROW_NUMBER analytic function:

SELECT profile_id,
       last_profile_date_time
FROM   (
  SELECT profile_id,
         last_profile_date_time,
         ROW_NUMBER()
           OVER (ORDER BY last_profile_date_time DESC) AS rn
  FROM   table_name
  WHERE  user_id = 100
  ORDER BY last_profile_date_time DESC
) q
WHERE  RN = 1;

or both databases support the FETCH FIRST ROW ONLY syntax:

SELECT profile_id,
       last_profile_date_time
FROM   table_name
WHERE  user_id = 100
ORDER BY last_profile_date_time DESC
FETCH FIRST ROW ONLY;

Which, for the sample data:

CREATE TABLE table_name (
  ID         INT,
  USER_ID    INT,
  PROFILE_ID INT,
  LAST_PROFILE_DATE_TIME TIMESTAMP
);

INSERT INTO table_name (id, user_id, profile_id, last_profile_date_time)
  VALUES (1, 100, 101, TIMESTAMP '2023-06-04 08:35:19.5393' );
INSERT INTO table_name (id, user_id, profile_id, last_profile_date_time)
  VALUES (2, 100, 102, TIMESTAMP '2023-06-05 08:35:19.5393' );

Both output:

profile_id last_profile_date_time
102 2023-06-05 08:35:19.5393

PostgreSQL fiddle Oracle fiddle

huangapple
  • 本文由 发表于 2023年6月5日 17:46:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76405198.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定