J'ai un tableau qui répertorie les versions de logiciels installés:
id | userid | version | datetime
----+--------+---------+------------------------
111 | 75 | 10075 | 2013-03-12 13:40:58.770
112 | 75 | 10079 | 2013-03-12 13:41:01.583
113 | 78 | 10065 | 2013-03-12 14:18:24.463
114 | 78 | 10079 | 2013-03-12 14:22:20.437
115 | 78 | 10079 | 2013-03-12 14:24:01.830
116 | 78 | 10080 | 2013-03-12 14:24:06.893
117 | 74 | 10080 | 2013-03-12 15:31:42.797
118 | 75 | 10079 | 2013-03-13 07:03:56.157
119 | 75 | 10080 | 2013-03-13 07:05:23.137
120 | 65 | 10080 | 2013-03-13 07:24:33.323
121 | 68 | 10080 | 2013-03-13 08:03:24.247
122 | 71 | 10080 | 2013-03-13 08:20:16.173
123 | 78 | 10080 | 2013-03-13 08:28:25.487
124 | 56 | 10080 | 2013-03-13 08:49:44.503
Je voudrais afficher tous les champs d'un enregistrement de chaque userid
mais seulement la version la plus récente (la version est également une varchar
).
Vous ne spécifiez pas comment vous voulez que les liens soient gérés, mais cela le fera si vous voulez que les doublons soient affichés;
SELECT a.* FROM MyTable a
LEFT JOIN MyTable b
ON a.userid=b.userid
AND CAST(a.version AS INT) < CAST(b.version AS INT)
WHERE b.version IS NULL
Si vous voulez éliminer les doublons et s'ils existent, choisissez le plus récent d'entre eux, vous devrez étendre quelque peu la requête.
WITH cte AS (SELECT *, CAST(version AS INT) num_version FROM MyTable)
SELECT a.id, a.userid, a.version, a.datetime
FROM cte a LEFT JOIN cte b
ON a.userid=b.userid
AND (a.num_version < b.num_version OR
(a.num_version = b.num_version AND a.[datetime]<b.[datetime]))
WHERE b.version IS NULL
Si vous utilisez SQL-Server (minimum 2005), vous pouvez utiliser CTE
avec la fonction ROW_NUMBER
. Vous pouvez utiliser CAST
pour la version pour obtenir le bon ordre:
WITH cte
AS (SELECT id,
userid,
version,
datetime,
Row_number()
OVER (
partition BY userid
ORDER BY Cast(version AS INT) DESC) rn
FROM [dbo].[table])
SELECT id,
userid,
version,
datetime
FROM cte
WHERE rn = 1
ORDER BY userid
ROW_NUMBER
retourne toujours un enregistrement, même s'il existe plusieurs utilisateurs avec la même version (top). Si vous souhaitez renvoyer tous les "enregistrements top-version-user", vous devez remplacer ROW_NUMBER
par DENSE_RANK
.
WITH records
AS
(
SELECT id, userid, version, datetime,
ROW_NUMBER() OVER (PARTITION BY userID
ORDER BY version DESC) rn
FROM tableName
)
SELECT id, userid, version, datetime
FROM records
WHERE RN =1
Le code suivant affiche ce que vous voulez et est excellent pour la performance!
select * from the_table t where cast([version] as int) =
(select max(cast([version] as int)) from the_table where userid = t.userid)
Je pense que cela peut résoudre votre problème:
SELECT id,
userid,
Version,
datetime FROM (
SELECT id,
userid,
Version,
datetime ,
DENSE_Rank() over (Partition BY id order by datetime asc) AS Rankk
FROM [dbo].[table]) RS
WHERE Rankk<2
J'ai utilisé la fonction RANK pour vos besoins ....
Si mon expérience en tuning m'a appris quelque chose, les généralités sont très mauvaises.
MAIS, si vous obtenez le Top X
dans la table, c’est-à-dire des centaines de milliers ou des millions. CROSS APPLY
est presque universellement le meilleur. En fait, si vous le comparez, l’application croisée exécute de manière cohérente et admirable également à des échelles plus petites (sur des dizaines de milliers) et couvre toujours le avec des liens exigence potentielle.
Quelque chose comme:
select
id
,userid
,version
,datetime
from
TheTable t
cross apply
(
select top 1 --with ties
id
from
TheTable
where
userid = t.userid
order by
datetime desc
)
select l.* from the_table l
left outer join the_table r
on l.userid = r.userid and l.version < r.version
where r.version is null