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.
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.
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.
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
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
SELECT TOP 1 * FROM tbl_CompanyMaster
where Companyid >= (SELECT MAX(Companyid) - 1 FROM tbl_CompanyMaster)
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
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
Si vous avez besoin de le faire, mais:
id
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
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.
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
select * from TABLE_NAME order by COLUMN_NAME desc limit 1,1 ;
Où COLUMN_NAME
devrait être "clé primaire" ou "Unique"
SELECT field_name FROM (SELECT TOP 2 field_name FROM table_name
ORDER BY field_name DESC)
WHERE rownum = 2;