Ich habe folgende Tabelle:
create table test (
company_id integer not null,
client_id integer not null,
client_status text,
unique (company_id, client_id)
);
insert into test values
(1, 1, 'y'), -- company1
(2, 2, null), -- company2
(3, 3, 'n'), -- company3
(4, 4, 'y'), -- company4
(4, 5, 'n'),
(5, 6, null), -- company5
(5, 7, 'n')
;
Grundsätzlich gibt es 5 verschiedene Unternehmen, jedes hat einen oder mehrere Kunden und jeder Kunde hat den Status: 'y' oder 'n' (kann auch null sein).
Was ich tun muss, ist, alle Paare (company_id, client_id)
für alle Unternehmen auszuwählen , für die es mindestens einen Kunden gibt, dessen Status nicht 'n' ('y' oder null) ist. Für die obigen Beispieldaten sollte die Ausgabe also sein:
company_id;client_id
1;1
2;2
4;4
4;5
5;6
5;7
Ich habe etwas mit Fensterfunktionen versucht, kann aber nicht herausfinden, wie die Anzahl ALLER Clients mit der Anzahl der Clients verglichen werden kann STATUS = 'n'
.
select company_id,
count(*) over (partition by company_id) as all_clients_count
from test
-- where all_clients_count != ... ?
Ich habe herausgefunden, wie das geht, bin mir aber nicht sicher, ob es der richtige Weg ist:
select sub.company_id, unnest(sub.client_ids)
from (
select company_id, array_agg(client_id) as client_ids
from test
group by company_id
having count(*) != count( (case when client_status = 'n' then 1 else null end) )
) sub
postgresql
postgresql-9.4
user606521
quelle
quelle
UNIQUE
eingeschränkt(company_id, client_id)
. Ihre Testdaten lassen jedoch den Eindruck entstehen(company_id, client_id)
, dass sie tatsächlich einzigartig sind. Ist es? Wenn nicht, benötigen Sie * alle * qualifizierenden Zeilen oder jede Kombination voncompany_id
undclient_id
nur einmal ?Antworten:
Grundsätzlich suchen Sie nach dem Ausdruck:
Die Spalte
client_status
sollte eigentlich vom Datentyp seinboolean
, nichttext
, was den einfacheren Ausdruck ermöglichen würde:Das Handbuch enthält Details im Kapitel Vergleichsoperatoren .
Angenommen, Ihr tatsächlicher Tisch hat eine
UNIQUE
oder einePK
Einschränkung , kommen wir zu:Abfragen
Alle diese tun dasselbe (was Sie gefragt haben), was am schnellsten von der Datenverteilung abhängt:
Oder:
Oder:
Boolesche Werte sortieren
FALSE
->TRUE
->NULL
in aufsteigender Sortierreihenfolge. AlsoFALSE
kommt zuletzt in absteigender Reihenfolge. Wenn ein anderer Wert verfügbar ist, wird dieser zuerst ausgewählt ...Die hinzugefügte PK wird mit einem nützlichen Index für diese Abfragen implementiert. Wenn Sie dennoch schneller möchten, fügen Sie einen Teilindex für Abfrage 1 hinzu:
Sie könnten auch Fensterfunktionen verwenden, aber das wäre langsamer. Beispiel mit
first_value()
:Bei vielen Zeilen pro
company_id
Zeile kann eine dieser Techniken dennoch schneller sein:quelle
Ich habe dich vielleicht missverstanden, aber ich stelle mir so etwas vor wie:
wird funktionieren. Koaleszenz wird verwendet, um 'y' null zuzuordnen, aber alles andere als 'n' sollte reichen
Die Verwendung einer OLAP-Funktion kann uns einen "Join" ersparen:
Hier ordnen wir null -> 'y' und 'n' -> null zu. Da count (x) Zeilen zählt, in denen x nicht null ist, zählen wir Zeilen, in denen client_status <> 'n' ist. Ich habe eine OLAP-Funktion verwendet, um GROUP BY zu vermeiden, was bedeutet, dass wir die Tabelle nur einmal referenzieren müssen.
quelle
Ich denke, das kann ein bisschen vereinfacht werden:
quelle
Eine Standard-SQL-Abfrage unten sollte funktionieren
quelle