jak odpytywać sql o najnowszą datę rekordu dla każdego użytkownika

Mam tabelę, która jest zbiorem wpisów, kiedy użytkownik był zalogowany.

username, date,      value
--------------------------
brad,     1/2/2010,  1.1
fred,     1/3/2010,  1.0
bob,      8/4/2009,  1.5
brad,     2/2/2010,  1.2
fred,     12/2/2009, 1.3

etc..

Jak utworzyć zapytanie, które poda mi najnowszą datę dla każdego użytkownika?

Update: zapomniałem, że muszę mieć wartość, która pasuje do ostatniej daty.

Author: a_horse_with_no_name, 2010-03-09

21 answers

select t.username, t.date, t.value
from MyTable t
inner join (
    select username, max(date) as MaxDate
    from MyTable
    group by username
) tm on t.username = tm.username and t.date = tm.MaxDate
 257
Author: RedFilter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-09 18:56:12

Korzystanie z funkcji okien (działa w Oracle, Postgres 8.4, SQL Server 2005, DB2, Sybase, Firebird 3.0, MariaDB 10.3)

select * from (
    select
        username,
        date,
        value,
        row_number() over(partition by username order by date desc) as rn
    from
        yourtable
) t
where t.rn = 1
 57
Author: dotjoe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-27 06:20:45

Widzę, że większość programistów używa zapytania inline, nie biorąc pod uwagę jego wpływu na ogromne dane.

Po prostu możesz to osiągnąć poprzez:

SELECT a.username, a.date, a.value
FROM myTable a
LEFT OUTER JOIN myTable b
ON a.username = b.username 
AND a.date < b.date
WHERE b.username IS NULL
ORDER BY a.date desc;
 22
Author: sujeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-02 01:31:31

Aby uzyskać cały wiersz zawierający maksymalną datę dla użytkownika:

select username, date, value
from tablename where (username, date) in (
    select username, max(date) as date
    from tablename
    group by username
)
 17
Author: Alison R.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-09 18:54:15
SELECT *     
FROM MyTable T1    
WHERE date = (
   SELECT max(date)
   FROM MyTable T2
   WHERE T1.username=T2.username
)
 6
Author: Manix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-03 14:18:46

Ten powinien dać ci poprawny wynik dla edytowanego pytania.

Pod-zapytanie upewnia się, że znajdzie tylko wiersze ostatniej daty, A zewnętrzne GROUP BY zajmie się powiązaniami. Jeśli istnieją dwa wpisy dla tego samego dnia dla tego samego użytkownika, zwróci on ten z najwyższą value.

SELECT t.username, t.date, MAX( t.value ) value
FROM your_table t
JOIN (
       SELECT username, MAX( date ) date
       FROM your_table
       GROUP BY username
) x ON ( x.username = t.username AND x.date = t.date )
GROUP BY t.username, t.date
 2
Author: Peter Lang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-09 18:54:11

Dla Oracle sortuje wynik ustawiony w porządku malejącym i pobiera pierwszy rekord, więc otrzymasz najnowszy rekord:

select * from mytable
where rownum = 1
order by date desc
 1
Author: user2014518,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-05 19:51:17
SELECT * FROM TABEL1 WHERE DATE= (SELECT MAX(CREATED_DATE) FROM TABEL1)
 1
Author: AJAY,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-29 12:02:29
SELECT Username, date, value
 from MyTable mt
 inner join (select username, max(date) date
              from MyTable
              group by username) sub
  on sub.username = mt.username
   and sub.date = mt.date

Rozwiązuje zaktualizowany problem. Może to nie działać tak dobrze na dużych stołach, nawet przy dobrym indeksowaniu.

 0
Author: Philip Kelley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-09 18:53:52
SELECT *
FROM ReportStatus c
inner join ( SELECT 
  MAX(Date) AS MaxDate
  FROM ReportStatus ) m
on  c.date = m.maxdate
 0
Author: Narmadha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-18 11:13:01
SELECT t1.username, t1.date, value
FROM MyTable as t1
INNER JOIN (SELECT username, MAX(date)
            FROM MyTable
            GROUP BY username) as t2 ON  t2.username = t1.username AND t2.date = t1.date
 0
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-27 15:34:39

Select * from table1 where lastest_date=(select Max(latest_date) from table1 where user=yourUserName)

Zapytanie wewnętrzne zwróci ostatnią datę dla bieżącego użytkownika, zapytanie zewnętrzne pobierze wszystkie dane zgodnie z wynikiem zapytania wewnętrznego.

 0
Author: Dheeraj Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-04 10:12:54

Użyłem tego sposobu, aby pobrać ostatni rekord dla każdego użytkownika, który mam na stole. Było to zapytanie, aby uzyskać ostatnią lokalizację sprzedawcy, zgodnie z ostatnim czasem wykrytym na urządzeniach PDA.

CREATE FUNCTION dbo.UsersLocation()
RETURNS TABLE
AS
RETURN
Select GS.UserID, MAX(GS.UTCDateTime) 'LastDate'
From USERGPS GS
where year(GS.UTCDateTime) = YEAR(GETDATE()) 
Group By GS.UserID
GO
select  gs.UserID, sl.LastDate, gs.Latitude , gs.Longitude
        from USERGPS gs
        inner join USER s on gs.SalesManNo = s.SalesmanNo 
        inner join dbo.UsersLocation() sl on gs.UserID= sl.UserID and gs.UTCDateTime = sl.LastDate 
        order by LastDate desc
 0
Author: Mahmoud Hawa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-27 14:39:57

Moja mała kompilacja

  • self join better than nested select
  • Ale group by nie daje primary key co jest lepsze dla join
  • klucz ten może być podany przez partition by w połączeniu z first_value (docs )

Oto zapytanie:

select
 t.*
from 
 Table t inner join (
  select distinct first_value(ID) over(partition by GroupColumn order by DateColumn desc) as ID
  from Table
  where FilterColumn = 'value'
 ) j on t.ID = j.ID

Plusy:

  • Filtruj dane za pomocą instrukcji where używając dowolnej kolumny
  • select dowolne kolumny z przefiltrowanych wierszy

Wady:

  • Need MS SQL Serwer od 2012 roku.
 0
Author: resnyanskiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-23 05:24:42

Zrobiłem trochę dla mojej aplikacji jak to:

Poniżej znajduje się zapytanie:

select distinct i.userId,i.statusCheck, l.userName from internetstatus 
as i inner join login as l on i.userID=l.userID 
where nowtime in((select max(nowtime) from InternetStatus group by userID));    
 0
Author: Sajee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 12:16:37

Z mojego doświadczenia wynika, że najszybszym sposobem jest pobranie każdego wiersza, dla którego nie ma nowszego wiersza w tabeli. Oto mały benchmark z niektórymi danymi, które mam pod ręką.

Kolejną zaletą jest to, że używana składnia jest bardzo prosta i że znaczenie zapytania jest dość łatwe do zrozumienia(weź wszystkie wiersze tak, że nie ma nowszego wiersza dla nazwy użytkownika, która jest brana pod uwagę).

NIE ISTNIEJE

SELECT username, value
FROM t
WHERE NOT EXISTS (
  SELECT *
  FROM t AS witness
  WHERE witness.date > t.date
);

Wyjaśnij całkowity koszt : 2.38136

ROW_NUMBER

SELECT username, value
FROM (
  SELECT username, value, row_number() OVER (PARTITION BY username ORDER BY date DESC) AS rn
  FROM t
) t2
WHERE rn = 1

Całkowity koszt : 61.5823

INNER JOIN

SELECT t.username, t.value
FROM t
INNER JOIN (
  SELECT username, MAX(date) AS date
  FROM t
  GROUP BY username
) tm ON t.username = tm.username AND t.date = tm.date;

Wyjaśnij całkowity koszt : 67.5439

LEFT OUTER JOIN

SELECT username, value
FROM t
LEFT OUTER JOIN t AS w ON t.username = w.username AND t.date < w.date
WHERE w.username IS NULL

Wyjaśnij całkowity koszt : 62.964


Plany wyjaśnień pochodzą z bazy danych zawierającej około 10 tysięcy wierszy, zapisanych jako XML. Używane zapytania zawierają również predykat "group_id = '1'".

 0
Author: Fabian Pijcke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-22 12:36:47

Jest to podobne do jednej z powyższych odpowiedzi, ale moim zdaniem jest o wiele prostsze i bardziej uporządkowane. Ponadto, pokazuje dobre wykorzystanie cross apply oświadczenie. Dla SQL Server 2005 i nowszych...

select
    a.username,
    a.date,
    a.value,
from yourtable a
cross apply (select max(date) 'maxdate' from yourtable a1 where a.username=a1.username) b
where a.date=b.maxdate
 0
Author: James Moore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-27 05:16:35

Można również użyć funkcji Rank analityczny

    with temp as 
(
select username, date, RANK() over (partition by username order by date desc) as rnk from t
)
select username, rnk from t where rnk = 1
 0
Author: kushal bhola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-26 01:42:15

Można użyć funkcji zbiorczej MAX i GROUP BY

SELECT username, MAX(date), value FROM tablename GROUP BY username, value
 -1
Author: Matthew Jones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-09 18:52:14
SELECT DISTINCT Username, Dates,value 
FROM TableName
WHERE  Dates IN (SELECT  MAX(Dates) FROM TableName GROUP BY Username)


Username    Dates       value
bob         2010-02-02  1.2       
brad        2010-01-02  1.1       
fred        2010-01-03  1.0       
 -1
Author: wara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-27 13:46:59

Powinno to również działać, aby uzyskać wszystkie najnowsze wpisy dla użytkowników.

SELECT username, MAX(date) as Date, value
FROM MyTable
GROUP BY username, value
 -1
Author: Vipin Kohli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-04 13:41:44