Je suis aux prises avec un problème que j'ai dans TSQL, j'ai besoin d'obtenir les 10 premiers résultats pour chaque utilisateur d'une table qui pourrait contenir plus de 10 résultats.TSQL difficile jointure problème
Mon approche naturelle (et procédurale) est "pour chaque utilisateur dans la table T, sélectionnez les 10 premiers résultats classés par date".
Chaque fois que j'essaie de formuler la question dans mon esprit dans une approche basée sur un ensemble, je continue à courir dans le terme «foreach».
Est-il possible de faire quelque chose comme ceci:
SELECT *
FROM table AS t1
INNER JOIN (
SELECT TOP 10 *
FROM table AS t2
WHERE t2.id = t1.id
ORDER BY date DESC
)
Ou encore
SELECT ( SELECT TOP 10 *
FROM table AS t2
WHERE t2.id = t1.id
ORDER BY date )
FROM table AS t1
Ou est-il une autre solution à cela en utilisant des tables de temp que je devrais penser?
EDIT:
Juste pour être parfaitement clair - je dois les 10 meilleurs résultats pour chaque utilisateur dans le tableau, par exemple 10 * N où N = nombre d'utilisateurs.
EDIT:
En réponse à une suggestion faite par RBarryYoung, je vais avoir un problème, ce qui est le mieux démontré avec le code:
CREATE TABLE #temp (id INT, date DATETIME)
INSERT INTO #temp (id, date) VALUES (1, GETDATE())
INSERT INTO #temp (id, date) VALUES (1, GETDATE())
SELECT *
FROM #temp AS t1
CROSS APPLY (
SELECT TOP 1 *
FROM #temp AS t2
WHERE t2.id = t1.id
ORDER BY t2.date DESC
) AS t2
DROP TABLE #temp
en cours, vous pouvez voir que cette ne limite pas les résultats au TOP 1 ... Est-ce que je fais quelque chose de mal ici?
EDIT:
Il semble que mon dernier exemple fourni un peu de confusion. Voici un exemple montrant ce que je veux faire:
CREATE TABLE #temp (id INT, date DATETIME)
INSERT INTO #temp (id, date) VALUES (1, GETDATE())
INSERT INTO #temp (id, date) VALUES (1, GETDATE())
INSERT INTO #temp (id, date) VALUES (1, GETDATE())
INSERT INTO #temp (id, date) VALUES (2, GETDATE())
SELECT *
FROM #temp AS t1
CROSS APPLY
(
SELECT TOP 2 *
FROM #temp AS t2
WHERE t2.id = t1.id
ORDER BY t2.date DESC
) AS t2
DROP TABLE #temp
Ce sorties:
1 2009-08-26 09:05:56.570 1 2009-08-26 09:05:56.583
1 2009-08-26 09:05:56.570 1 2009-08-26 09:05:56.583
1 2009-08-26 09:05:56.583 1 2009-08-26 09:05:56.583
1 2009-08-26 09:05:56.583 1 2009-08-26 09:05:56.583
1 2009-08-26 09:05:56.583 1 2009-08-26 09:05:56.583
1 2009-08-26 09:05:56.583 1 2009-08-26 09:05:56.583
2 2009-08-26 09:05:56.583 2 2009-08-26 09:05:56.583
Si je distingue:
SELECT DISTINCT t1.id
FROM #temp AS t1
CROSS APPLY
(
SELECT TOP 2 *
FROM #temp AS t2
WHERE t2.id = t1.id
ORDER BY t2.date DESC
) AS t2
Je reçois
1
2
I besoin
1
1
2
Est-ce que quelqu'un sait si c'est possible?
EDIT:
Le code suivant fera cette
WITH RowTable AS
(
SELECT
id, date, ROW_NUMBER() OVER (PARTITION BY id ORDER BY date DESC) AS RowNum
FROM #temp
)
SELECT *
FROM RowTable
WHERE RowNum <= 2;
Je posté dans les commentaires, mais il n'y a pas de mise en forme de code, il ne semble pas très agréable.
vous n'avez pas demandé à limiter les résultats t TOP 1, avez-vous? Vous avez demandé à imiter les résultats pour l'utilisateur TOP 1 * foreach *, ce qui est différent. Mais je suis vrai que ma réponse originale ne tenait pas compte du fait que l'utilisateur (id) avait été dupliqué dans la table source: corrigé maintenant. – RBarryYoung
@RBarryYoung - Désolé mon pote. J'ai ajouté un exemple pour démontrer exactement ce que je veux. C'était un peu simpliste de moi: ( – Khanzor