select 最近的条目
select the most recent entry
我有以下 table:
LOCATION_ID, PERSON_ID, DATE
3, 65, 2016-06-03
7, 23, 2016-10-28
3, 23, 2016-08-05
5, 65, 2016-07-14
我想在 PL/SQL 中构建一个 select 查询 select 具有 最近 location_id 的记录person_id。对于上面的示例,期望的结果应该是:
LOCATION_ID, PERSON_ID, DATE
5, 65, 2016-07-14
7, 23, 2016-10-28
(日期表示为'YYYY-MM-DD')
谢谢!
您可以先通过 PERSON_ID
对结果进行分组并选择 MAX(DATE)
.
来提取每个人的最近事件
然后在这两列上将 table 与其自身连接起来以检索 LOCATION_ID
SELECT
YOUR_TABLE.LOCATION_ID,
YOUR_TABLE.PERSON_ID,
YOUR_TABLE.DATE
FROM
(SELECT
PERSON_ID, MAX(DATE) AS max_date
FROM
YOUR_TABLE
GROUP BY
PERSON_ID
) AS t1
LEFT JOIN
YOUR_TABLE
ON
YOUR_TABLE.PERSON_ID = t1.PERSON_ID
AND
YOUR_TABLE.DATE = t1.max_date
顺便说一下,你不应该使用像 DATE
这样的保留字作为列名。
这里 fiddle 展示它的工作原理:http://sqlfiddle.com/#!9/efdcb/2
@quasoft 是正确的。处理这类 GROUP BY
问题的另一种方法(当你想要 return 比你想要分组的列更多时。在你的情况下,你需要 return location_id, person_id。但是你只需要按person_id)分组,就是用analytical functions。
--schema:
CREATE TABLE my_table
(
location_id NUMBER,
person_id NUMBER,
date_ DATE
);
INSERT ALL
INTO my_table
VALUES (3, 65, To_date('2016-06-03', 'YYYY-MM-DD'))
INTO my_table
VALUES (7, 23, To_date('2016-10-28', 'YYYY-MM-DD'))
INTO my_table
VALUES (3, 23, To_date('2016-08-05', 'YYYY-MM-DD'))
INTO my_table
VALUES (5, 65, To_date('2016-07-14', 'YYYY-MM-DD'))
SELECT *
FROM dual;
--query:
WITH ordered
AS (SELECT location_id,
person_id,
date_,
Row_number()
over (
PARTITION BY person_id
ORDER BY date_ DESC) RN
FROM my_table)
SELECT location_id,
person_id,
date_
FROM ordered
WHERE rn = 1;
查询 ordered
按日期对每个组的行进行排序。主查询,returns是每组排序后的第1个。因此,它将 return 在这种情况下是最后一个(我们按 date_desc 排序)。
其他建议是正确的,但是当您使用 FIRST_VALUE and LAST_VALUE Analytic Functions
时最有可能是最紧凑和最快的解决方案
SELECT DISTINCT
FIRST_VALUE(LOCATION_ID) OVER (PARTITION BY PERSON_ID ORDER BY THE_DATE
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS LOCATION_ID,
PERSON_ID,
MAX(THE_DATE) OVER (PARTITION BY PERSON_ID) AS LAST_DATE
FROM YOUR_TABLE;
其他人更喜欢
SELECT
MAX(LOCATION_ID) KEEP (DENSE_RANK FIRST ORDER BY DATE) as LOCATION,
PERSON_ID,
MAX(DATE) as LAST_DATE
FROM YOUR_TABLE
GROUP BY PERSON_ID;
which也一样,不过我对这个子句不是很熟悉。参见 aggregate_function KEEP
这可能有用!
SELECT * FROM Your_Table A
JOIN (SELECT PERSON_ID,MAX(DATE) as MaxDate FROM Your_Table
GROUP BY PERSON_ID) B
ON A.PERSON_ID = B.PERSON_ID AND A.DATE = B.MaxDate
我有以下 table:
LOCATION_ID, PERSON_ID, DATE
3, 65, 2016-06-03
7, 23, 2016-10-28
3, 23, 2016-08-05
5, 65, 2016-07-14
我想在 PL/SQL 中构建一个 select 查询 select 具有 最近 location_id 的记录person_id。对于上面的示例,期望的结果应该是:
LOCATION_ID, PERSON_ID, DATE
5, 65, 2016-07-14
7, 23, 2016-10-28
(日期表示为'YYYY-MM-DD')
谢谢!
您可以先通过 PERSON_ID
对结果进行分组并选择 MAX(DATE)
.
然后在这两列上将 table 与其自身连接起来以检索 LOCATION_ID
SELECT
YOUR_TABLE.LOCATION_ID,
YOUR_TABLE.PERSON_ID,
YOUR_TABLE.DATE
FROM
(SELECT
PERSON_ID, MAX(DATE) AS max_date
FROM
YOUR_TABLE
GROUP BY
PERSON_ID
) AS t1
LEFT JOIN
YOUR_TABLE
ON
YOUR_TABLE.PERSON_ID = t1.PERSON_ID
AND
YOUR_TABLE.DATE = t1.max_date
顺便说一下,你不应该使用像 DATE
这样的保留字作为列名。
这里 fiddle 展示它的工作原理:http://sqlfiddle.com/#!9/efdcb/2
@quasoft 是正确的。处理这类 GROUP BY
问题的另一种方法(当你想要 return 比你想要分组的列更多时。在你的情况下,你需要 return location_id, person_id。但是你只需要按person_id)分组,就是用analytical functions。
--schema:
CREATE TABLE my_table
(
location_id NUMBER,
person_id NUMBER,
date_ DATE
);
INSERT ALL
INTO my_table
VALUES (3, 65, To_date('2016-06-03', 'YYYY-MM-DD'))
INTO my_table
VALUES (7, 23, To_date('2016-10-28', 'YYYY-MM-DD'))
INTO my_table
VALUES (3, 23, To_date('2016-08-05', 'YYYY-MM-DD'))
INTO my_table
VALUES (5, 65, To_date('2016-07-14', 'YYYY-MM-DD'))
SELECT *
FROM dual;
--query:
WITH ordered
AS (SELECT location_id,
person_id,
date_,
Row_number()
over (
PARTITION BY person_id
ORDER BY date_ DESC) RN
FROM my_table)
SELECT location_id,
person_id,
date_
FROM ordered
WHERE rn = 1;
查询 ordered
按日期对每个组的行进行排序。主查询,returns是每组排序后的第1个。因此,它将 return 在这种情况下是最后一个(我们按 date_desc 排序)。
其他建议是正确的,但是当您使用 FIRST_VALUE and LAST_VALUE Analytic Functions
时最有可能是最紧凑和最快的解决方案SELECT DISTINCT
FIRST_VALUE(LOCATION_ID) OVER (PARTITION BY PERSON_ID ORDER BY THE_DATE
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS LOCATION_ID,
PERSON_ID,
MAX(THE_DATE) OVER (PARTITION BY PERSON_ID) AS LAST_DATE
FROM YOUR_TABLE;
其他人更喜欢
SELECT
MAX(LOCATION_ID) KEEP (DENSE_RANK FIRST ORDER BY DATE) as LOCATION,
PERSON_ID,
MAX(DATE) as LAST_DATE
FROM YOUR_TABLE
GROUP BY PERSON_ID;
which也一样,不过我对这个子句不是很熟悉。参见 aggregate_function KEEP
这可能有用!
SELECT * FROM Your_Table A
JOIN (SELECT PERSON_ID,MAX(DATE) as MaxDate FROM Your_Table
GROUP BY PERSON_ID) B
ON A.PERSON_ID = B.PERSON_ID AND A.DATE = B.MaxDate