J'ai un tableau avec des chiffres comme celui-ci (le statut est GRATUIT ou ASSIGNÉ)
état du numéro id_set ----------------------- 1 000001 ATTRIBUÉ 1 000002 GRATUIT 1 000003 ATTRIBUÉ 1 000004 GRATUIT 1 000005 GRATUIT 1 000006 ATTRIBUÉ 1 000007 ATTRIBUÉ 1 000008 GRATUIT 1 000009 GRATUIT 1 000010 GRATUIT 1 000011 ATTRIBUÉ 1 000012 ATTRIBUÉ 1 000013 ATTRIBUÉ 1 000014 GRATUIT 1 000015 ATTRIBUÉ
et j'ai besoin de trouver "n" nombres consécutifs, donc pour n = 3, la requête retournerait
1 000008 GRATUIT 1 000009 GRATUIT 1 000010 GRATUIT
Il ne devrait renvoyer que le premier groupe possible de chaque id_set (en fait, il ne serait exécuté que pour id_set par requête)
Je vérifiais les fonctions de WINDOW, essayais quelques requêtes comme COUNT(id_number) OVER (PARTITION BY id_set ROWS UNBOUNDED PRECEDING)
, mais c'est tout ce que j'ai eu :) Je ne pouvais pas penser à la logique, comment faire cela dans Postgres.
Je pensais à créer une colonne virtuelle en utilisant les fonctions WINDOW comptant les lignes précédentes pour chaque nombre où status = 'FREE', puis sélectionnez le premier nombre, où count est égal à mon nombre "n".
Ou peut-être regrouper les numéros par statut, mais uniquement d'un ASSIGNÉ à un autre ASSIGNÉ et sélectionner uniquement les groupes contenant au moins "n" numéros
ÉDITER
J'ai trouvé cette requête (et l'ai un peu modifiée)
WITH q AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY id_set, status ORDER BY number) AS rnd,
ROW_NUMBER() OVER (PARTITION BY id_set ORDER BY number) AS rn
FROM numbers
)
SELECT id_set,
MIN(number) AS first_number,
MAX(number) AS last_number,
status,
COUNT(number) AS numbers_count
FROM q
GROUP BY id_set,
rnd - rn,
status
ORDER BY
first_number
qui produit des groupes de numéros GRATUITS / ATTRIBUÉS, mais j'aimerais avoir tous les numéros du seul premier groupe qui remplit la condition
id_set
ou un seul? Veuillez mettre à jour votre question si cela a été conçu comme faisant partie du début. (Pour que les autres puissent voir toutes les exigences et offrir leurs suggestions ou mettre à jour leurs réponses.)Une variante simple et rapide :
Nécessite une séquence de chiffres sans intervalle
number
(comme prévu dans la question).Fonctionne pour n'importe quel nombre de valeurs possibles en
status
plus'FREE'
, même avecNULL
.La principale caractéristique est de soustraire
row_number()
denumber
après avoir éliminé les lignes de non-qualification. Les numéros consécutifs finissent dans le mêmegrp
- etgrp
sont également garantis dans l' ordre croissant .Ensuite, vous pouvez
GROUP BY grp
et compter les membres. Puisque vous semblez vouloir la première occurrence,ORDER BY grp LIMIT 1
et vous obtenez la position de départ et la longueur de la séquence (peut être> = n ).Ensemble de rangées
Pour obtenir un ensemble réel de nombres, ne recherchez pas le tableau une autre fois. Beaucoup moins cher avec
generate_series()
:Si vous voulez réellement une chaîne avec des zéros en tête comme vous l'affichez dans vos exemples de valeurs, utilisez
to_char()
avec leFM
modificateur (mode de remplissage):SQL Fiddle avec cas de test étendu et les deux requêtes.
Réponse étroitement liée:
la source
C'est une façon assez générique de le faire.
Gardez à l'esprit que cela dépend de votre
number
colonne consécutive. Si ce n'est pas une fonction Window et / ou une solution de type CTE sera probablement nécessaire:la source
M.number-consec+1
(par exemple, pour 10, cela devrait être le cas10-3+1=8
).number
champ. Bon appel au calcul, je vais le corriger.EXISTS
pourrait être simplifié. Comme nous devons seulement nous assurer que n anciennes lignes existent, nous pouvons supprimer leAND status = 'FREE'
. Et je changerais la condition dans le 2èmeEXISTS
àstatus <> 'FREE'
durcir contre options ajoutées à l'avenir.Cela ne renverra que le premier des 3 chiffres. Il ne nécessite pas que les valeurs de
number
soient consécutives. Testé chez SQL-Fiddle :Et cela montrera tous les nombres (où il y a 3
'FREE'
positions consécutives ou plus ):la source
Dans ce cas, 5 nombres consécutifs - donc la différence doit être 4 ou en d'autres termes
count(r3.number) = n
etr2.number = r1.number + n - 1
.Avec jointures:
la source
JOIN
syntaxe moderne ?la source
{ }
bouton de l'éditeur. Prendre plaisir!