Выберите последнюю запись для идентификатора в день - Oracle pl sql - PullRequest
0 голосов
/ 14 февраля 2020

Как мне написать оператор sql, который возвращает самую последнюю запись в день, по идентификатору. Например. с данными, как показано ниже.

Id   Name        Comment         Value    DateTime
1    Tim         Test            100      02/06/2020 15:05:12
2    Sue         House           200      03/06/2020 08:25:01
1    Tim         Test            150      02/06/2020 18:05:12
3    Doug        Cars            680      10/05/2019 04:45:10
2    Sue         Tennis          200      03/06/2020 10:35:15

Я бы получил:

Id   Name        Comment         Value    DateTime
1    Tim         Test            150      02/06/2020 18:05:12
3    Doug        Cars            680      10/05/2019 04:45:10
2    Sue         Tennis          200      03/06/2020 10:35:15

Нужен ли мне запрос на дополнительный выбор, который группирует по максимальному времени даты?

Ответы [ 3 ]

1 голос
/ 14 февраля 2020

Я бы выбрал оконную функцию:

select id, name, comment, value, dateTime from
(
  select id, name, comment, value, dateTime
           , last_value(dateTime) over( partition by id, trunc(datetime)
                                        order by dateTime 
             rows  BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) lv
) 
where dateTime=lv
0 голосов
/ 14 февраля 2020

При использовании FIRST / LAST вам даже не нужен подзапрос:

WITH t(ID, NAME, COMMENT_, VALUE, DateTime) AS (
    SELECT 1,'Tim','Test', 100, TO_DATE('02/06/2020 15:05:12', 'dd/mm/yyyy hh24:mi:ss') FROM dual
    UNION ALL SELECT 2,'Sue','House', 200, TO_DATE('03/06/2020 08:25:01', 'dd/mm/yyyy hh24:mi:ss') FROM dual
    UNION ALL SELECT 1,'Tim','Test', 150, TO_DATE('02/06/2020 18:05:12', 'dd/mm/yyyy hh24:mi:ss') FROM dual
    UNION ALL SELECT 3,'Doug','Cars', 680, TO_DATE('10/05/2019 04:45:10', 'dd/mm/yyyy hh24:mi:ss') FROM dual
    UNION ALL SELECT 2,'Sue','Tennis', 300, TO_DATE('03/06/2020 10:35:15', 'dd/mm/yyyy hh24:mi:ss') FROM dual
    UNION ALL SELECT 2,'Sue','Steets', 400, TO_DATE('10/10/2020 10:35:15', 'dd/mm/yyyy hh24:mi:ss') FROM dual)
SELECT ID, 
    MAX(NAME) KEEP (DENSE_RANK LAST ORDER BY DateTime) AS NAME,
    MAX(COMMENT_) KEEP (DENSE_RANK LAST ORDER BY DateTime) AS COMMENT_,
    MAX(VALUE) KEEP (DENSE_RANK LAST ORDER BY DateTime) AS VALUE,
    MAX(DateTime) KEEP (DENSE_RANK LAST ORDER BY DateTime) AS DateTime
FROM t
GROUP BY ID, TRUNC(DateTime);

+------------------------------------------+
|ID|NAME|COMMENT_|VALUE|DATETIME           |
+------------------------------------------+
|1 |Tim |Test    |150  |02.06.2020 18:05:12|
|2 |Sue |Tennis  |300  |03.06.2020 10:35:15|
|2 |Sue |Steets  |400  |10.10.2020 10:35:15|
|3 |Doug|Cars    |680  |10.05.2019 04:45:10|
+------------------------------------------+
0 голосов
/ 14 февраля 2020

Один простой способ сделать это - отфильтровать с помощью коррелированного подзапроса:

select t.*
from mytable t
where t.datetime = (
    select max(t1.datetime)
    from mytable t1
    where t1.datetime >= trunc(t.datetime)
    and t1.datetime < trunc(t.datetime) + 1
)

Вам также может понравиться анти- left join подход:

select t.*
from mytable t
left join mytable t1 
    on  t1.datetime > t.datetime
    and t1.datetime >= trunc(t.datetime)
    and t1.datetime < trunc(t.datetime) + 1
where t1.id is null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...