mysql - requete - sql limit




Comment sélectionner la nième ligne dans une table de base de données SQL? (19)

SERVEUR SQL

Sélectionnez le nième disque en haut

SELECT * FROM (
SELECT 
ID, NAME, ROW_NUMBER() OVER(ORDER BY ID) AS ROW
FROM TABLE 
) AS TMP 
WHERE ROW = n

sélectionner n 'ème enregistrement du bas

SELECT * FROM (
SELECT 
ID, NAME, ROW_NUMBER() OVER(ORDER BY ID DESC) AS ROW
FROM TABLE 
) AS TMP 
WHERE ROW = n

Je suis intéressé par l'apprentissage (idéalement) des méthodes agnostiques de base de données de la sélection de la nième rangée à partir d'une table de base de données. Il serait également intéressant de voir comment cela peut être réalisé en utilisant la fonctionnalité native des bases de données suivantes:

  • serveur SQL
  • MySQL
  • PostgreSQL
  • SQLite
  • Oracle

Je suis en train de faire quelque chose comme ce qui suit dans SQL Server 2005, mais je serais intéressé de voir les approches plus agnostiques des autres:

WITH Ordered AS (
SELECT ROW_NUMBER() OVER (ORDER BY OrderID) AS RowNumber, OrderID, OrderDate
FROM Orders)
SELECT *
FROM Ordered
WHERE RowNumber = 1000000

Crédit pour le SQL ci-dessus: Weblog de Firoz Ansari

Mise à jour: Voir la réponse de Troels Arvin concernant la norme SQL. Troels, avez-vous des liens que nous pouvons citer?


1 petit changement: n-1 au lieu de n.

select *
from thetable
limit n-1, 1

C'est ainsi que je le ferais dans DB2 SQL, je crois que le RRN (numéro d'enregistrement relatif) est stocké dans la table par l'O / S;

SELECT * FROM (                        
   SELECT RRN(FOO) AS RRN, FOO.*
   FROM FOO                         
   ORDER BY RRN(FOO)) BAR             
 WHERE BAR.RRN = recordnumber

Contrairement à ce que prétendent certaines réponses, la norme SQL n'est pas muette sur ce sujet.

Depuis SQL: 2003, vous pouvez utiliser des "fonctions de fenêtre" pour ignorer les lignes et limiter les ensembles de résultats.

Et dans SQL: 2008, une approche légèrement plus simple a été ajoutée, en utilisant
OFFSET skip ROWS FETCH FIRST n ROWS ONLY

Personnellement, je ne pense pas que l'ajout de SQL: 2008 était vraiment nécessaire, donc si j'étais ISO, je l'aurais écarté d'une norme déjà assez grande.


Dans Sybase SQL Anywhere:

SELECT TOP 1 START AT n * from table ORDER BY whatever

Ne pas oublier la commande ou c'est sans signification.


Il me semble que, pour être efficace, vous devez 1) générer un nombre aléatoire entre 0 et un de moins que le nombre d'enregistrements de base de données, et 2) être capable de sélectionner la ligne à cette position. Malheureusement, différentes bases de données ont différents générateurs de nombres aléatoires et différentes manières de sélectionner une ligne à un emplacement dans un ensemble de résultats. En général, vous spécifiez le nombre de lignes à ignorer et le nombre de lignes souhaitées. Voici quelque chose qui fonctionne pour moi dans SQLite:

select * 
from Table 
limit abs(random()) % (select count(*) from Words), 1;

Cela dépend de pouvoir utiliser une sous-requête dans la clause limit (qui dans SQLite est LIMIT <recs to skip>, <recs to take>) La sélection du nombre d'enregistrements dans une table devrait être particulièrement efficace, faisant partie de la base de données. méta-données, mais cela dépend de la mise en œuvre de la base de données. En outre, je ne sais pas si la requête va réellement construire le jeu de résultats avant de récupérer le Nième enregistrement, mais j'espère que ce n'est pas nécessaire. Notez que je ne spécifie pas une clause "order by". Il peut être préférable de "trier" quelque chose comme la clé primaire, qui aura un index - obtenir le Nième enregistrement d'un index pourrait être plus rapide si la base de données ne peut pas obtenir le Nième enregistrement de la base de données sans construire le jeu de résultats .


Je ne suis pas sûr de tout le reste, mais je sais que SQLite et MySQL n'ont aucun ordre de rangée "par défaut". Dans ces deux dialectes, au moins, l'extrait suivant récupère la 15ème entrée de the_table, en la triant par date / heure d'ajout:

SELECT * FROM the_table ORDER BY added DESC LIMIT 1,15

(bien sûr, vous devez avoir un champ DATETIME ajouté, et le définir à la date / heure que l'entrée a été ajoutée ...)


Je soupçonne que c'est très inefficace, mais c'est une approche assez simple, qui a travaillé sur un petit jeu de données sur lequel j'ai essayé.

select top 1 field
from table
where field in (select top 5 field from table order by field asc)
order by field desc

Ceci obtiendrait le 5ème article, changez le deuxième nombre supérieur pour obtenir un nième article différent

Serveur SQL seulement (je pense) mais devrait fonctionner sur les anciennes versions qui ne supportent pas ROW_NUMBER ().


La syntaxe LIMIT / OFFSET dans PostgreSQL est:

SELECT
    *
FROM
    mytable
ORDER BY
    somefield
LIMIT 1 OFFSET 20;

Cet exemple sélectionne la 21ème ligne. OFFSET 20 indique à Postgres d'ignorer les 20 premiers enregistrements. Si vous ne spécifiez pas de clause ORDER BY , il n'y a aucune garantie quant à l'enregistrement que vous obtiendrez, ce qui est rarement utile.

Apparemment, la norme SQL est silencieuse sur le problème de la limite en dehors des fonctions de fenêtrage fou, ce qui explique pourquoi tout le monde l'implémente différemment.


Mais vraiment, tout cela n'est-il pas vraiment juste des trucs de salon pour une bonne conception de base de données en premier lieu? Les quelques fois où j'ai eu besoin d'une fonctionnalité comme celle-ci, c'était pour une simple requête unique pour faire un rapport rapide. Pour tout vrai travail, l'utilisation de trucs comme ceux-ci est une source d'ennuis. Si la sélection d'une ligne particulière est nécessaire, il suffit d'avoir une colonne avec une valeur séquentielle et d'en finir avec elle.


Par exemple, si vous voulez sélectionner chaque 10ème ligne dans MSSQL, vous pouvez utiliser;

SELECT * FROM (
  SELECT
    ROW_NUMBER() OVER (ORDER BY ColumnName1 ASC) AS rownumber, ColumnName1, ColumnName2
  FROM TableName
) AS foo
WHERE rownumber % 10 = 0

Il suffit de prendre le MOD et de changer le numéro 10 ici n'importe quel nombre que vous voulez.


Pour SQL Server, une manière générique de passer par numéro de ligne est la suivante: SET ROWCOUNT @row - @ row = le numéro de ligne sur lequel vous souhaitez travailler.

Par exemple:

set rowcount 20 --définit la ligne à la 20ème rangée

choisir la viande, le fromage de dbo.sandwich - sélectionner les colonnes de la table au 20ème rang

set rowcount 0 --définit rowcount sur toutes les lignes

Cela retournera les informations de la 20ème rangée. Assurez-vous de mettre dans le rowcount 0 après.

Je connais Noobish, mais je suis un SQL Noob et je l'ai utilisé alors que puis-je dire?


Rien d'extraordinaire, pas de fonctions spéciales, au cas où vous utilisez Caché comme je le fais ...

SELECT TOP 1 * FROM (
  SELECT TOP n * FROM <table>
  ORDER BY ID Desc
)
ORDER BY ID ASC

Étant donné que vous avez une colonne ID ou une colonne datastamp vous pouvez faire confiance.


SQL 2005 et supérieur a cette fonctionnalité intégrée. Utilisez la fonction ROW_NUMBER (). Il est excellent pour les pages Web avec une navigation de style << Précédente et Suivante >>:

Syntaxe:

SELECT
    *
FROM
    (
        SELECT
            ROW_NUMBER () OVER (ORDER BY MyColumnToOrderBy) AS RowNum,
            *
        FROM
            Table_1
    ) sub
WHERE
    RowNum = 23

Vérifiez-le sur SQL Server:

Select top 10 * From emp 
EXCEPT
Select top 9 * From emp

Cela vous donnera 10ème RANG de table emp!


Voici une solution rapide de votre confusion.

SELECT * FROM table ORDER BY `id` DESC LIMIT N, 1

Ici, vous pouvez obtenir la dernière ligne en remplissant N = 0, la deuxième en dernier par N = 1, la quatrième en remplissant N = 3 et ainsi de suite.

C'est une question très commune au cours de l'interview et c'est très simple.

Plus loin Si vous voulez un montant, un identifiant ou un ordre de tri numérique, vous pouvez opter pour la fonction CAST dans MySQL.

SELECT DISTINCT (`amount`) FROM cart ORDER BY CAST( `amount` AS SIGNED ) DESC LIMIT 4 , 1

En remplissant N = 4, vous pourrez obtenir le cinquième enregistrement du montant le plus élevé de la table CART. Vous pouvez adapter votre nom de champ et de table et trouver la solution.


incroyable que vous pouvez trouver un moteur SQL exécutant celui-ci ...

WITH sentence AS
(SELECT 
    stuff,
    row = ROW_NUMBER() OVER (ORDER BY Id)
FROM 
    SentenceType
    )
SELECT
    sen.stuff
FROM sentence sen
WHERE sen.row = (ABS(CHECKSUM(NEWID())) % 100) + 1

SELECT
    top 1 *
FROM
    table_name
WHERE
    column_name IN (
        SELECT
            top N column_name
        FROM
            TABLE
        ORDER BY
            column_name
    )
ORDER BY
    column_name DESC

J'ai écrit cette requête pour trouver Nth row. Exemple avec cette requête serait

SELECT
    top 1 *
FROM
    Employee
WHERE
    emp_id IN (
        SELECT
            top 7 emp_id
        FROM
            Employee
        ORDER BY
            emp_id
    )
ORDER BY
    emp_id DESC

select * from 
(select * from ordered order by order_id limit 100) x order by 
x.order_id desc limit 1;

Commencez par sélectionner les 100 premières lignes en les classant par ordre croissant, puis sélectionnez la dernière ligne en les ordonnant en descendant et en les limitant à 1. Toutefois, cette instruction est très coûteuse car elle accède aux données deux fois.





postgresql