2016-04-06 16 views
4

Ich habe eine Tabelle, die Nummern (Telefonnummern) und einen Code (kostenlos oder nicht verfügbar) enthält.Finden Sie fortlaufende freie Nummern in der Tabelle

Jetzt muss ich Reihe von 30 fortlaufenden Nummern finden, wie 079xxx100 - 079xxx130, und alle von ihnen, um freien Status zu haben.

Hier ist ein Beispiel, wie meine Tabelle wie folgt aussieht: in diesem Beispiel

CREATE TABLE numere 
(
    value int, 
    code varchar(10) 
); 


INSERT INTO numere (value,code) 
Values 
(123100, 'free'), 
(123101, 'free'), 
... 
(123107, 'booked'), 
(123108, 'free'), 
(... 
(123130, 'free'), 
(123131, 'free'), 
... 

(123200, 'free'), 
(123201, 'free'), 
... 
(123230, 'free'), 
(123231, 'free'), 
... 

Ich brauche eine SQL-Abfrage, zu bekommen, den 123.200-123.230 Bereich (und alle nächsten verfügbaren Bereiche) me.

Nun fand ich ein Beispiel, mehr oder weniger tun, was ich brauche:

select value, code 
from numere 
where value >= (select a.value 
       from numere a 
       left join numere b on a.value < b.value 
            and b.value < a.value + 30 
            and b.code = 'free' 
       where a.code = 'free' 
       group by a.value 
       having count(b.value) + 1 = 30) 
limit 30 

aber dies ist nur die ersten 30 verfügbaren Zahlen zurückkehrt, und nicht in meinem Bereich (0-30). (Und dauert 13 Minuten auszuführen, hehe ..)

Wenn jemand eine Idee hat, lass es mich wissen (Ich bin mit SQL Server)

Antwort

2

Dies scheint, wie es in meinem Dataset funktioniert. Ändern Sie die Auswahl und sehen Sie, ob sie mit Ihrem Tabellennamen zusammenarbeitet.

DECLARE @numere TABLE 
(
value int, 
code varchar(10) 
); 


INSERT INTO @numere (value,code) SELECT 123100, 'free' 

WHILE (SELECT COUNT(*) FROM @numere)<=30 
BEGIN 
    INSERT INTO @numere (value,code) SELECT MAX(value)+1, 'free' FROM @numere 
END 

UPDATE @numere 
SET code='booked' 
WHERE value=123105 

select * 
from @numere n1 
inner join @numere n2 ON n1.value=n2.value-30 
    AND n1.code='free' 
    AND n2.code='free' 
LEFT JOIN @numere n3 ON n3.value>=n1.value 
    AND n3.value<=n2.value 
    AND n3.code<>'free' 
WHERE n3.value IS NULL 
+0

Danke, das funktioniert gut, mir 30 aufeinanderfolgende freie Nummern zu finden. Ich denke, von 00-30 Bereich nur finden, werde ich es manuell tun, weil ich nicht so viele Bereiche haben wird avialable :). Wenn jemand eine schnelle Möglichkeit hat, sie von 00 zu finden (ich würde wie eine Teilfunktion denken, die letzten Ziffern ausschneiden, dann prüfen, ob sie innerhalb des 0-30 Bereichs liegen. –

+0

Den letzten Teil Ihres Kommentars nicht verstehen. Wie war die Leistung im Vergleich zu der Methode, die Sie ursprünglich verwendet? – UnhandledExcepSean

+0

In Bezug auf Leistung, habe ich jetzt nur in einer Dummy-SQLite-Datenbank getestet, morgen werde ich mit Produktionsdatenbank überprüfen. Aber es sieht aus, dass die gleiche Leistung ist, mehr oder weniger mein Kommentar, dies ist ein echter Anwendungsfall, einige Unternehmen (mit 30 Mitarbeitern), wollen alle ihre Nummern haben, wie 079xxxx00-079xxxx30, (die letzten 2 Ziffern, von 0 bis 30) und ich muss aus der Datenbank auswählen wenn es freie Nummern gibt, innerhalb dieses Bereichs Anywhay, deine Antwort ist schon extremely usseful, wie es ist, danke –

1

Dies ist das übliche Island- und Gap-Problem.

; with cte as 
( 
    select *, grp = row_number() over (order by value) 
      - row_number() over (partition by code order by value) 
    from numere 
), 
grp as 
(
    select grp 
    from cte 
    group by grp 
    having count(*) >= 30 
) 
select c.grp, c.value, c.code 
from grp g 
    inner join cte c on g.grp = c.grp 
1

Sie können Tabellendaten für Lücken zwischen den gebuchten Zahlen mit folgenden SQL-Abfrage abfragen, wo SQL LEAD() analytical function

;with cte as (
select 
    value, lead(value) over (order by value) nextValue 
from numere 
where code = 'booked' 
), cte2 as (
select 
value gapstart, nextValue gapend, 
(nextValue - value - 1) [number count in gap] from cte 
where value < nextValue - 1 
) 
select * 
from cte2 
where [number count in gap] >= 30 

Sie überprüfen Find Missing Numbers and Gaps in a Sequence using SQL das SQL-Tutorial verwendet wird

Ich hoffe, es hilft,

1

Kann momentan nicht getestet werden, aber dies könnte funktionieren:

SELECT a.Value FROM (SELECT Value FROM numere WHERE Code='free' ) a INNER Join (SELECT Value FROM numere WHERE code='free' ) b ON b.Value BETWEEN a.Value+1 AND a.Value+29 GROUP BY a.Value HAVING COUNT(b.Value) >= 29 ORDER BY a.Value ASC

Die Ausgabe sollte alle Zahlen sein, die folgenden 29 freie Nummern haben (so ist es 30 aufeinanderfolgende Zahlen)

+0

Danke, dieses funktioniert und zeigt nur die Werte, nicht auch die Codes an (ich bin zu SQL sehr neu, aber ich versuche zu ändern, also komme ich in Ausgabe beide Spalten). –

Verwandte Themen