Astuce de la différence entre numéros de ligne
Soustraire ROW_NUMBER d’une séquence pour regrouper les valeurs consécutives en îlots
Astuce de la différence entre numéros de ligne est une leçon Coding Interview Prep gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Coding Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Coding Interview Prep comprend 4 leçons au total.
La clé d’îlot la plus élégante
L’astuce de la différence avec ROW_NUMBER est la technique que les intervieweurs souhaitent le plus souvent voir pour les îlots d’entiers ou de dates consécutifs. Elle produit la clé de groupe par une seule soustraction, sans LAG ni somme cumulée.
L’idée est simple : soustraire un ROW_NUMBER à la valeur elle-même. Dans toute suite de valeurs consécutives, la valeur et le numéro de ligne augmentent exactement de 1 à chaque étape ; leur différence reste donc constante sur toute la suite. Cette constante est la clé de votre îlot.
Pourquoi la différence reste constante
Considérez deux lignes adjacentes d’une suite consécutive. En passant de l’une à l’autre, la valeur augmente de 1 et le numéro de ligne augmente de 1. En les soustrayant, les +1 s’annulent ; value - row_number ne change donc pas.
Mais dès qu’un intervalle apparaît, la valeur augmente de plus de 1 tandis que le numéro de ligne n’augmente toujours que de 1. La différence prend une nouvelle valeur constante. Ce changement sépare précisément un îlot du suivant.
Visualiser nos données
Rappelez-vous les jours de connexion 1, 2, 3, 7, 8, 10. Présentons côte à côte le numéro de ligne et la différence :
- jour 1, numéro de ligne 1, différence 0
- jour 2, numéro de ligne 2, différence 0
- jour 3, numéro de ligne 3, différence 0
- jour 7, numéro de ligne 4, différence 3
- jour 8, numéro de ligne 5, différence 3
- jour 10, numéro de ligne 6, différence 4
Les différences (0,0,0,3,3,4) partitionnent parfaitement les lignes en trois îlots. Même différence signifie même îlot.
SELECT
day_no,
ROW_NUMBER() OVER (ORDER BY day_no) AS rn,
day_no - ROW_NUMBER() OVER (ORDER BY day_no) AS grp
FROM logins
ORDER BY day_no;Réduire les lignes en îlots
En utilisant la différence comme clé de groupe, la requête finale applique le regroupement standard. Placez la différence dans une CTE, puis effectuez un GROUP BY dessus :
Cette requête renvoie les mêmes trois îlots qu’auparavant, mais le SQL est plus court et plus clair que la version avec LAG et somme cumulée. Pour les suites d’entiers ou les suites à pas régulier, c’est la solution à privilégier en premier.
WITH keyed AS (
SELECT
day_no,
day_no - ROW_NUMBER() OVER (ORDER BY day_no) AS grp
FROM logins
)
SELECT
MIN(day_no) AS start_day,
MAX(day_no) AS end_day,
COUNT(*) AS length
FROM keyed
GROUP BY grp
ORDER BY start_day;Le piège : les valeurs doivent progresser de un
L'astuce de la différence simple suppose que la séquence augmente d'exactement 1 à chaque étape. C'est vrai pour les entiers denses et les jours calendaires consécutifs, mais cela échoue si vos valeurs progressent d'une autre quantité fixe ou si des doublons existent.
- Même les valeurs paires 2,4,6,8 sembleront former des lacunes avec une soustraction valeur moins numéro de ligne.
- Les valeurs en double faussent l'alignement, car le numéro de ligne continue d'augmenter tandis que la valeur reste inchangée.
Comprendre cette limite et savoir comment la corriger, c'est ce qui distingue une astuce apprise par cœur d'une véritable compréhension.
Corriger les séquences à pas fixe
Si les valeurs progressent d'une constante connue k plutôt que de 1, normalisez-les d'abord : divisez la valeur par k (ou utilisez value / k pour les entiers) afin que chaque étape redevienne égale à 1, puis soustrayez le numéro de ligne.
Par exemple, pour des nombres pairs progressant de 2, utilisez day_no / 2 - ROW_NUMBER(). La valeur normalisée augmente alors de 1 pour chaque élément consécutif, ce qui rétablit la propriété de différence constante.
SELECT
val,
(val / 2) - ROW_NUMBER() OVER (ORDER BY val) AS grp
FROM even_series
ORDER BY val;Appliquer cette méthode aux dates
Les dates constituent le cas réel le plus courant. Les dates calendaires ne peuvent pas être soustraites directement d'un numéro de ligne ; convertissez donc d'abord la date en nombre de jours. Dans Postgres, soustrayez une date d'ancrage fixe pour obtenir un nombre entier de jours, puis appliquez la même astuce.
Comme deux jours calendaires consécutifs diffèrent de 1, la différence entre le nombre de jours et le numéro de ligne est de nouveau constante au sein d'un îlot.
WITH keyed AS (
SELECT
login_date,
(login_date - DATE '2000-01-01')
- ROW_NUMBER() OVER (ORDER BY login_date) AS grp
FROM daily_logins
)
SELECT MIN(login_date) AS start_date,
MAX(login_date) AS end_date,
COUNT(*) AS days_in_run
FROM keyed GROUP BY grp ORDER BY start_date;Calcul des différences de dates selon le dialecte
La conversion d'une date en entier varie selon le moteur, et les personnes qui vous interrogent apprécient que vous connaissiez les différences entre les dialectes :
- Postgres : soustrayez un littéral de date :
login_date - DATE '2000-01-01'produit un entier. - MySQL : utilisez
DATEDIFF(login_date, '2000-01-01'). - SQL Server : utilisez
DATEDIFF(day, '2000-01-01', login_date).
Une solution encore plus élégante sur certains moteurs consiste à soustraire directement ROW_NUMBER jours de la date à l'aide de l'arithmétique des intervalles, puis à regrouper avec GROUP BY selon la date d'ancrage obtenue.
SELECT
login_date,
login_date - (ROW_NUMBER() OVER (ORDER BY login_date)
* INTERVAL '1 day') AS grp_date
FROM daily_logins;Ajouter des partitions par groupe
Pour obtenir des îlots par utilisateur, partitionnez le numéro de ligne selon la colonne de groupe. Point essentiel : la clé de groupe doit alors inclure également la colonne de partitionnement, car deux utilisateurs différents peuvent produire par hasard la même valeur de différence.
Utilisez donc GROUP BY à la fois sur user_id et sur la différence calculée. Oublier l'identifiant utilisateur dans le GROUP BY final est une erreur subtile que les personnes qui vous interrogent aiment repérer.
WITH keyed AS (
SELECT user_id, day_no,
day_no - ROW_NUMBER()
OVER (PARTITION BY user_id ORDER BY day_no) AS grp
FROM logins
)
SELECT user_id, MIN(day_no) AS start_day,
MAX(day_no) AS end_day, COUNT(*) AS len
FROM keyed
GROUP BY user_id, grp
ORDER BY user_id, start_day;Astuce ou LAG : laquelle utiliser
Deux techniques fiables font désormais partie de votre boîte à outils. Choisissez délibérément :
- Différence avec le numéro de ligne : la solution la plus courte et la plus claire pour les séquences de valeurs à pas régulier (entiers denses, dates consécutives). C'est le premier choix lorsque l'adjacence signifie « diffère d'une constante ».
- LAG plus somme cumulée : plus flexible lorsque l'adjacence ne correspond pas à un pas numérique fixe, par exemple pour « même état que la ligne précédente » ou pour des règles personnalisées irrégulières.
Expliquez votre choix et sa raison pendant l'entretien ; le raisonnement impressionne davantage que la syntaxe.
Gérer les doublons de manière préventive
Si une valeur peut se répéter et que vous souhaitez malgré tout obtenir un îlot par séquence consécutive, dédoublonnez d'abord avec DISTINCT ou une étape de regroupement afin que le numéro de ligne corresponde à chaque valeur une seule fois. Vous pouvez aussi utiliser DENSE_RANK à la place de ROW_NUMBER afin que les valeurs ex æquo partagent le même rang.
Demandez toujours à la personne qui vous interroge si des doublons peuvent apparaître ; la bonne protection dépend de la question de savoir si les doublons doivent prolonger la séquence ou être ignorés à l'intérieur de celle-ci.
WITH d AS (SELECT DISTINCT day_no FROM logins)
SELECT day_no,
day_no - ROW_NUMBER() OVER (ORDER BY day_no) AS grp
FROM d;Vérification rapide
Assurez-vous de comprendre pourquoi cette astuce fonctionne.
Récapitulatif : l'astuce de la différence
Vous disposez maintenant de la clé d'îlot la plus simple :
- Formule de la clé :
value - ROW_NUMBER() OVER (ORDER BY value)est constante pour chaque séquence consécutive. - Regroupez avec
GROUP BYselon la différence pour obtenir le début, la fin et la longueur. - Pour les séquences à pas fixe, normalisez d'abord (divisez par le pas).
- Pour les dates, convertissez-les en nombre entier de jours à l'aide de la fonction de différence du dialecte.
- Par groupe : utilisez
PARTITION BYpour le numéro de ligne et incluez la colonne de groupe dans leGROUP BYfinal. - Protégez-vous des doublons avec
DISTINCTouDENSE_RANK.
Nous délaissons ensuite les îlots pour nous intéresser aux espaces vides : la recherche des lacunes.
Questions Fréquemment Posées
La leçon « Astuce de la différence entre numéros de ligne » est-elle gratuite ?
Oui — le texte complet de « Astuce de la différence entre numéros de ligne » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Coding Interview Prep, passe à CoddyKit PRO. Le cours Coding Interview Prep comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Astuce de la différence entre numéros de ligne » ?
Soustraire ROW_NUMBER d’une séquence pour regrouper les valeurs consécutives en îlots Tu pratiques Coding Interview Prep avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Coding Interview Prep ?
Aucune expérience préalable n'est requise. Coding Interview Prep sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Astuce de la différence entre numéros de ligne » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Coding Interview Prep ?
Oui. Chaque leçon Coding Interview Prep inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Reconnaître un problème de lacunes et d’îlots
- Astuce de la différence entre numéros de ligne
- Trouver les lacunes d’une séquence
- Îlots avec changements de date et de statut