web-dev-qa-db-fra.com

Prendre l’avant-dernière ligne avec une seule sélection dans SQL Server?

J'essayais de sélectionner l'avant dernière ligne avec SQL Server. J'ai donc écrit une requête comme celle-ci:

SELECT TOP 1 * From Cinema 
WHERE CinemaID!=(SELECT TOP 1 CinemaID 
                 FROM Cinema
                 ORDER BY CinemaID DESC)                      
ORDER BY CinemaID DESC 

et il a fait ce dont j'avais besoin. Mais je veux faire la même chose avec un seul choix.

J'ai lu que la clause LIMIT dansMySqlfait cela. Mais je n’ai trouvé aucun équivalent De cela. J'apprécie donc toute aide pour trouver quelque chose d'utile.

22
3yanlis1bos

Pour obtenir la 2ème dernière ligne d'une sélection:

SELECT TOP 1 * From
(select Top 2 * from Cinema ORDER BY CinemaID DESC) x                     
ORDER BY CinemaID

C'est vraiment seulement "une" sélection parce que la sélection externe est sur seulement 2 lignes.

34
Bohemian

La meilleure façon de procéder (compatible avec le standard ANSI SQL) consiste à utiliser un CTE (Common Table Expression) avec la fonction ROW_NUMBER:

;WITH OrderedCinemas AS
(
   SELECT 
       CinemaID, CinemaName, 
       ROW_NUMBER() OVER(ORDER BY CinemaID DESC) AS 'RowNum'
   FROM dbo.Cinema
)
SELECT 
   CinemaID, CinemaName
FROM OrderedCinemas
WHERE RowNum = 2

En utilisant cette construction, vous pouvez obtenir très facilement la deuxième valeur la plus élevée - ou la cinquième valeur la plus élevée (WHERE RowNum = 5) ou les trois premières lignes (WHERE RowNum <= 3) ou ce dont vous avez besoin - les valeurs CinemaID sont simplement ordonnées et numérotées séquentiellement pour votre utilisation.

12
marc_s

Ce qui suit ne fonctionne pas, expliquez pourquoi: Utilisation de la colonne dérivée de ranking-fonction dans la clause where (SQL Server 2008)

Je vais le garder ici pour l'exhaustivité:


SELECT row_number() OVER (ORDER BY col) r, *
FROM tbl
WHERE r = 2

Plus d'infos: http://www.bidn.com/blogs/marcoadf/bidn-blog/379/ranking-functions-row_row-number-vs-rank-vs-dense_rank-vs-ntile


Donc, je pense que le moyen le plus lisible de le faire est:

SELECT * FROM (SELECT row_number() OVER (ORDER BY col) r, * FROM tbl) q
WHERE r = 2
7
MK.

Puisque cette (ancienne) question n'a pas été marquée avec une version spécifique de SQL Server et qu'aucune (très bonne) réponse n'utilise qu'une seule clause SELECT - pour la bonne raison que cela n'était pas possible dans les anciennes versions - en voici une qui fonctionne uniquement dans les dernières versions 2012+:

SELECT c.* 
FROM dbo.Cinema AS c                    
ORDER BY CinemaID DESC
OFFSET 1 ROW
FETCH FIRST 1 ROW ONLY ; 

Testé à SQLFiddle

5
ypercubeᵀᴹ
SELECT TOP 1 * FROM tbl_CompanyMaster 
where Companyid >= (SELECT MAX(Companyid) - 1 FROM tbl_CompanyMaster)
2
Milan Hbk

Donc, dans l’idée de n’utiliser qu’une seule clause SELECT, comme indiqué dans le PO, et d’abuser complètement de T-SQL en général, je propose quelque chose que je ne recommanderais jamais, jamais, d’utiliser dans une production qui respecte néanmoins les critères énoncés:

update Cinema
set Cinema.SomeField = Cinema.SomeField
output inserted.*
from Cinema
inner join 
(
    select top 2 CinemaID, ROW_NUMBER() over (order by CinemaID desc) as RowNum
    from Cinema
) rsRowNum on rsRowNum.CinemaID = Cinema.CinemaID
where RowNum = 2
1
Bert

Cette requête fonctionnera également pour SQLITE

SELECT *  From
(select * from Cinema ORDER BY CinemaID  DESC LIMIT 2) AS name                    
ORDER BY CinemaID LIMIT 1
1
Atif Mahmood

Si vous avez besoin de le faire, mais: 

  • la colonne est différente de id
  • vous devez commander par une colonne spécifique
  • ne peut pas utiliser SELECT sur la clause FROM (si vous utilisez d'anciennes versions d'Hibernate, par exemple).

Tu peux faire:

select top 1 * from Cinema
where date < (select MAX(date) from Cinema)
order by date desc
0
Dherik
select top 1* from(SELECT TOP 2 * From Cinema 
                   WHERE CinemaID
                   ORDER BY CinemaID DESC) XYZ
ORDER BY CinemaID

où XYZ n'est pas un mot clé. C'est juste une parole. Et Word peut être n'importe quoi.

0
Jaydip Modi

Vous n'utilisez qu'une seule instruction SELECT. Une instruction SELECT peut inclure un nombre arbitraire (plus ou moins) de sous-requêtes: sous-requêtes corrélées, sous-requêtes scalaires, etc., chacune avec sa propre clause SELECT. Mais ce n'est toujours qu'une seule instruction SELECT. 

Si vous souhaitez éviter une sous-requête, vous pouvez sélectionner le top 2 et ignorer celle que vous ne voulez pas. Ce type de programmation est cependant assez fragile. Vous devez vous rappeler quoi sauter à chaque fois; tôt ou tard, vous oublierez.

Deux sélections mais un peu plus vite

select top 1 * from(
SELECT TOP 2 * From Cinema 
WHERE CinemaID
ORDER BY CinemaID DESC) top2
Order by CinemaID
0
Tony Hopkinson
select * from TABLE_NAME order by COLUMN_NAME desc limit 1,1 ;

COLUMN_NAME devrait être "clé primaire" ou "Unique"

0
editinit
SELECT field_name FROM (SELECT TOP 2 field_name FROM table_name 
                        ORDER BY field_name DESC)
WHERE rownum = 2;
0
user3090065