Seite 1 von 1
select between mit subquery
Verfasst: Mo, 02. Aug 2021 22:57
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?
Re: select between mit subquery
Verfasst: Di, 03. Aug 2021 8:32
von Marcus Herz
Mir ist die Aufgabenstellung nicht klar. Weleche Überlappung?
Re: select between mit subquery
Verfasst: Di, 03. Aug 2021 8:49
von HaPe
- Überlappung
- ueberlappung.jpg (36.69 KiB) 4626 mal betrachtet
Re: select between mit subquery
Verfasst: Di, 03. Aug 2021 9:05
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.
Re: select between mit subquery
Verfasst: Di, 03. Aug 2021 9:08
von Marcus Herz
Das Ergebnis sollen 2 Sätze sein,
Elli und Falsch
weil es ja (noch) kein Kriterium gibt, wer eine Regel verletzt,
Re: select between mit subquery
Verfasst: Di, 03. Aug 2021 10:15
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
Re: select between mit subquery
Verfasst: Di, 03. Aug 2021 22:04
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
Re: select between mit subquery
Verfasst: Di, 03. Aug 2021 22:09
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.
Re: select between mit subquery
Verfasst: Di, 03. Aug 2021 22:20
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!