Je suis confronté à un problème plutôt intéressant. J'ai une table avec la structure suivante:
CREATE TABLE [dbo].[Event]
(
Id int IDENTITY(1,1) NOT NULL,
ApplicationId nvarchar(32) NOT NULL,
Name nvarchar(128) NOT NULL,
Description nvarchar(256) NULL,
Date nvarchar(16) NOT NULL,
Time nvarchar(16) NOT NULL,
EventType nvarchar(16) NOT NULL,
CONSTRAINT Event_PK PRIMARY KEY CLUSTERED ( Id ) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
)
)
Le problème est donc que je dois afficher ces données dans une grille. Il y a deux exigences. La première consiste à afficher tous les événements, quelle que soit l'application qui les a lancés. C’est simple: une instruction select fera le travail très facilement.
La deuxième exigence est de pouvoir regrouper les événements par Application
. En d’autres termes, affichez tous les événements de manière à ce que, si la variable ApplicationId
soit répétée plusieurs fois, ne saisissez que la dernière entrée de chaque application. La clé primaire de l'événement (Id) à ce stade n'est plus nécessaire dans cette requête/vue.
Vous pouvez également remarquer que la date et l'heure de l'événement sont au format chaîne. Cela convient car ils respectent les formats d'heure date standard: mm/jj/aaaa et hh: mm: ss. Je peux tirer ceux-ci comme suit:
Convert( DateTime, (Date + ' ' + Time)) AS 'TimeStamp'
Mon problème est que si j'utilise les fonctions AGGREGATE sur le reste des colonnes, je ne sais pas comment elles se comporteront:
SELECT
ApplicationId,
MAX(Name),
MAX(Description),
MAX( CONVERT(DateTime, (Date + ' ' + Time))) AS 'TimeStamp',
MAX( EventType )
FROM
Event
GROUP BY
ApplicationId
La raison pour laquelle j’ai hésité à le faire est qu’une fonction telle que MAX
renverra la plus grande valeur pour une colonne donnée à partir d’un (sous) ensemble d’enregistrements. Il ne faut pas forcément tirer le dernier disque!
Des idées sur la façon de ne sélectionner que le dernier enregistrement application par application?
Depuis SQL Server 2012, vous pouvez simplement
SELECT
[Month]
, [First] = FIRST_VALUE(SUM([Clicks])) OVER (ORDER BY [Month])
, [Last] = FIRST_VALUE(SUM([Clicks])) OVER (ORDER BY [Month] DESC)
FROM
[dbo].[Table]
GROUP BY [Month]
ORDER BY [Month]
Après 6 ans, une autre réponse pour SQL Server:
select t1.[Id], t2.[Value]
from [dbo].[Table] t1
outer apply (
select top 1 [Value]
from [dbo].[Table] t2
where t2.[Month]=t1.[Month]
order by [dbo].[Date] desc
)
Bien que j'aime bien la solution Postgresql bien mieux avec sa fonctionnalité distincte qui est plus agréable à taper et beaucoup plus efficace:
select distinct on (id),val
from tbl
order by id,val
Vous pouvez utiliser une sous-requête avec group by - l'argument group by n'a pas besoin d'être sélectionné. Cela suppose que Id est une incrémentation automatique, de sorte que la plus grande est la plus récente.
SELECT
ApplicationId,
Name,
Description,
CONVERT(DateTime, (Date + ' ' + Time)) AS 'TimeStamp',
EventType
FROM
Event e
WHERE
Id in (select max(Id) from Event GROUP BY ApplicationId)
Je pense que cela fonctionnera pour beaucoup de gens désirant aller chercher le dernier enregistrement inséré et il devrait être groupé par:
select * from (select * from TableName ORDER BY id DESC) AS x GROUP BY FieldName
Cela fonctionnera pour ce qui suit:
Structure de la table ID Nom Statut 1 Junaid Oui 2 Jawad Non 3 Fahad Oui 4 Junaid Non 5 Kashif Oui
Résultats après requête ci-dessus ID Nom Statut 4 Junaid Non 2 Jawad Non 3 Fahad Oui 4 Kashif Oui
Il en résulte simplement le dernier enregistrement du groupe par noms.
SELECT
E.ApplicationId,
E.Name,
E.Description,
CONVERT(DateTime, (E.Date + ' ' + E.Time)) AS 'TimeStamp',
E.EventType
FROM
Event E
JOIN (SELECT ApplicationId,
MAX(CONVERT(DateTime, (Date + ' ' + Time))) AS max_date
FROM Event
GROUP BY ApplicationId) EM
on EM.ApplicationId = E.ApplicationId
and EM.max_date = CONVERT(DateTime, (E.Date + ' ' + E.Time)))
Parce que vous n'avez pas de clause where dans le sous-ensemble d'enregistrements, ce sont tous les enregistrements. Mais vous mettez max sur la mauvaise colonne, je pense. Cette requête vous donnera ce que vous cherchez.
Select max(applicationid), name, description, CONVERT(DateTime, (Date + ' ' + Time))
from event
group by name, description, CONVERT(DateTime, (Date + ' ' + Time))
Pour ce faire, vous pouvez utiliser une table de sous-requête ou CTE:
;WITH CTE_LatestEvents as (
SELECT
ApplicationId,
MAX( CONVERT(DateTime, (Date + ' ' + Time))) AS 'LatestTimeStamp',
FROM
Event
GROUP BY
ApplicationId
)
SELECT
ApplicationId,
Name,
Description,
CONVERT(DateTime, (Date + ' ' + Time))) AS 'TimeStamp',
EventType
FROM
Event e
Join CTE_LatestEvents le
on e.applicationid = le.applicationid
and CONVERT(DateTime, (e.Date + ' ' + e.Time))) = le.LatestTimeStamp