select between mit subquery

Alles zum SQL-Dialekt

Moderator: Moderatoren

Antworten
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

select between mit subquery

Beitrag von Werner_Bayern »

Frage an die SQL-Profis,

gegeben ist eine Tabelle mit Wertebereiche:

id_von, id_bis, Name
1, 1000, Kevin
1001, 2000, Pascal
2001, 3000, Elli
2999, 4000, Falsch

Gesucht sind alle Sätze, deren Wertebereich überlappend ist, also hier der letzte Satz.

Bekomme es mit einem

Code: Alles auswählen

select * from blabla where id_von between (select id_von from blabla) and (select id_bis from blabla) and id_bis between ...
nicht hin:
als Ausdruck verwendete Unteranfrage ergab mehr als eine Zeile
Was auch nachvollziehbar ist.

Wie löse ich das? Mit IN?
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: select between mit subquery

Beitrag von Marcus Herz »

Mir ist die Aufgabenstellung nicht klar. Weleche Überlappung?
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
HaPe
1000 working lines a day
1000 working lines a day
Beiträge: 995
Registriert: So, 15. Nov 2015 17:44
Wohnort: 71665 Vaihingen-Enz
Hat sich bedankt: 17 Mal
Danksagung erhalten: 15 Mal

Re: select between mit subquery

Beitrag von HaPe »

Überlappung
Überlappung
ueberlappung.jpg (36.69 KiB) 3998 mal betrachtet
--
Hans-Peter
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: select between mit subquery

Beitrag von Marcus Herz »

Nicht genau gelesen!
Das ist wie mit der Terminierung von Aufträgen, welche überlappen sich nach einer Verschiebung:
- zeige alle Sätze, deren Max größer als das Minimum des nächsten Wertebreiches ist
- zeige alle Sätze, deren Minimum kleiner als das Maximum der kleineren Wertebreiche ist

Code: Alles auswählen

select * from 
(select name, min(id_von) as minvon, max(id_bis) as maxbis
from blabla
group by name) grpblabla
where maxbis > (select min(id_von) from balbla where  max(id_bis) > grpblabla.minvon)  /* alle späteren */
or minvon < (select max(id_bis) from balbla where  min(id_von) < grpblabla.maxbis)  /* alle früheren */
Habe mir keine Tabelle gemacht, um das zu testen.
Zuletzt geändert von Marcus Herz am Di, 03. Aug 2021 9:17, insgesamt 3-mal geändert.
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: select between mit subquery

Beitrag von Marcus Herz »

Das Ergebnis sollen 2 Sätze sein,
Elli und Falsch
weil es ja (noch) kein Kriterium gibt, wer eine Regel verletzt,
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
nightcrawler
1000 working lines a day
1000 working lines a day
Beiträge: 650
Registriert: Di, 24. Apr 2012 16:33
Wohnort: 72184 Weitingen
Hat sich bedankt: 3 Mal
Danksagung erhalten: 96 Mal
Kontaktdaten:

Re: select between mit subquery

Beitrag von nightcrawler »

Code: Alles auswählen

create table blabla(id_von integer, id_bis integer, name cichar(30));
insert into blabla(id_von, id_bis, name) values
(1, 1000, 'Kevin'),
(1001, 2000, 'Pascal'),
(2001, 3000, 'Elli'),
(2999, 4000, 'Falsch');
Ich gehe so vor:
1. die Tabelle mit sich selber kreuzen (INNER JOIN) auf alle Datensätze, bei denen b.von<a.bis:

Code: Alles auswählen

select a.*, b.* from blabla b
inner join blabla a on b.id_von<a.id_bis
2. Das Ergebnis weiter einschränken auf alle Datensätze, bei welchen b.bis>a.bis

Code: Alles auswählen

select a.*, b.* from blabla b
inner join blabla a on b.id_von<a.id_bis
and b.id_bis>a.id_bis
3. Evtl noch die Datensätze wegnehmen, bei denen a und b denselben anzeigen (bei <> nicht notwendigt, aber falls >= oder <= verwendet werden)

Code: Alles auswählen

select a.*, b.* from blabla b
inner join blabla a on b.id_von<a.id_bis
and b.id_bis>a.id_bis
and b.rowid<>a.rowid
Das Ergebnis ist dann erst der richtige Datensatz und darauf folgend der, der die Überschneidung begeht:
2001 3000 Elli 2999 4000 Falsch
--
Joachim
Joachim Dürr Softwareengineering
https://www.jd-engineering.de
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: select between mit subquery

Beitrag von Werner_Bayern »

Servus Marcus,

vielen Dank, da wäre ich nicht drauf gekommen. Leider schmeisst PG mir da den Fehler:
Aggregatfunktionen sind in WHERE nicht erlaubt
(select min(id_von) from blabla where max(id_bis...
und verweist auf das max(id_bis
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: select between mit subquery

Beitrag von Werner_Bayern »

Servus Joachim,

danke, das funktioniert, wenn ich die rowid weglasse, die kennt PG ja nicht. Aber da hab ich meinen Primärschlüssel, den ich dafür verwenden kann. =D>
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: select between mit subquery

Beitrag von Werner_Bayern »

Hatte mir zwischenzeitlich so geholfen:

Code: Alles auswählen

      oTicket:select("name, id_von, id_bis from " + SQL_TICKET_TABLES[3] + " where tabelle = '" + SQL_TICKET_TABLES[i] + "' order by id_von", "temp")
      do while .not. eof()
         nSatznr := recno()
         nID_von := temp->id_von
         nID_bis := temp->id_bis
         cName := temp->name
         dbSkip()
         do while .not. eof()
            if (nID_von >= temp->id_von .and. nID_von <= temp->id_bis) .or. (nID_bis >= temp->id_von .and. nID_bis <= temp->id_bis)
               aadd(aDoppelt, {cName, temp->name, nID_von, nID_bis, temp->id_von, temp->id_bis, SQL_TICKET_TABLES[i]})
            endif
            dbskip()
         enddo
         dbGoto(nSatznr)
         dbSkip()
      enddo
Muss das inner join wohl nur noch um die 2. Bedingung ergänzen, dann werden aus 16 Zeilen herkömmlichen Codes eine SQL-Anweisung! Toll!
es grüßt

Werner

<when the music is over, turn off the lights!>
Antworten