2014-11-21 10 views
8

In PostgreSQL 9 auf CentOS 6 gibt es 60.000 Datensätze in pref_users Tabelle:Links äußerer Join - Wie gibt man einen booleschen Wert für die Existenz in der zweiten Tabelle zurück?

# \d pref_users 
        Table "public.pref_users" 
    Column |   Type    |  Modifiers  
------------+-----------------------------+-------------------- 
id   | character varying(32)  | not null 
first_name | character varying(64)  | not null 
last_name | character varying(64)  | 
login  | timestamp without time zone | default now() 
last_ip | inet      | 
(... more columns skipped...) 

Und ein anderer Tisch hält rund 500 IDs von Benutzern, die mehr spielen nicht erlaubt sind:

# \d pref_ban2 
       Table "public.pref_ban2" 
    Column |   Type    | Modifiers 
------------+-----------------------------+--------------- 
id   | character varying(32)  | not null 
first_name | character varying(64)  | 
last_name | character varying(64)  | 
city  | character varying(64)  | 
last_ip | inet      | 
reason  | character varying(128)  | 
created | timestamp without time zone | default now() 
Indexes: 
    "pref_ban2_pkey" PRIMARY KEY, btree (id) 

In einem PHP Skript Ich versuche, alle 60000 Benutzer von pref_users in einer jQuery-dataTable anzuzeigen. Und ich möchte die gesperrten Benutzer markieren (die Benutzer gefunden in pref_ban2).

Das bedeutet, dass ich für jeden Datensatz in meiner Abfrage, die true oder false enthält, eine Spalte mit dem Namen ban benötigen.

So versuche ich eine linke äußere Verknüpfung Abfrage:

# select       
     b.id, -- how to make this column a boolean? 
     u.id, 
     u.first_name, 
     u.last_name, 
     u.city, 
     u.last_ip, 
     to_char(u.login, 'DD.MM.YYYY') as day 
from pref_users u left outer join pref_ban2 b on u.id=b.id 
limit 10; 
id | id | first_name | last_name | city  |  last_ip  | day  
----+----------+-------------+-----------+-------------+-----------------+------------ 
    | DE1  | Alex  |   | Bochum  | 2.206.0.224  | 21.11.2014 
    | DE100032 | Княжна Мэри |   | London  | 151.50.61.131 | 01.02.2014 
    | DE10011 | Aлександр Ш |   | Симферополь | 37.57.108.13 | 01.01.2014 
    | DE10016 | Semen10  |   | usa   | 69.123.171.15 | 25.06.2014 
    | DE10018 | Горловка |   | Горловка | 178.216.97.214 | 25.09.2011 
    | DE10019 | -Дмитрий- |   | пермь  | 5.140.81.95  | 21.11.2014 
    | DE10047 | Василий  |   | Cумы  | 95.132.42.185 | 25.07.2014 
    | DE10054 | Maedhros |   | Чикаго  | 207.246.176.110 | 26.06.2014 
    | DE10062 | ssergw  |   | москва  | 46.188.125.206 | 12.09.2014 
    | DE10086 | Вадим  |   | Тула  | 109.111.26.176 | 26.02.2012 
(10 rows) 

Wie Sie die b.id Spalte oben leer sehen kann - weil diese 10 Benutzer sind nicht verboten.

Wie erhalten Sie einen false Wert in dieser Spalte anstelle einer Zeichenfolge?

Und ich bin nicht nach einigen coalesce oder case Ausdruck, aber ich bin auf der Suche nach "der richtige" Weg, um eine solche Abfrage zu tun.

Antwort

8

Eine CASE- oder COALESCE-Anweisung mit einem Outer Join ist der richtige Weg, dies zu tun.

select 
    CASE 
    WHEN b.id IS NULL THEN true 
    ELSE false 
    END AS banned,       
    u.id, 
    u.first_name, 
    u.last_name, 
    u.city, 
    u.last_ip, 
    to_char(u.login, 'DD.MM.YYYY') as day 
from pref_users u 
left outer join pref_ban2 b 
    on u.id=b.id 
limit 10; 
+0

Vielen Dank für Ihre Antwort, aber sollte ich nicht besser (effektiver) 'exist' hier verwenden? –

+0

So 'EXISTS' fungiert als ein Filter. Wenn Sie 'EXISTS' verwenden, erhalten Sie den Datensatz nur dann nicht, wenn er herausgefiltert wird. Wenn Sie einen 'boolean'-Wert anzeigen möchten, sind Sie mit einem' CASE' besser dran. –

+0

Zu diesem Zeitpunkt könnten Sie 'EXISTS' anstelle von' OUTER JOIN' verwenden, aber das wird die boolesche Logik nicht ändern. –

3

"IS NULL" und "IS NOT NULL" eine boolean zurückgeben, so sollte dies es einfach machen.

Ich denke, das ist alles was Sie brauchen?

SELECT       
     b.id IS NOT NULL as is_banned, -- The value of "is_banned" will be a boolean 

Nicht sicher, ob Sie das "NICHT" oder nicht brauchen, aber Sie werden einen bool entweder erhalten.

+0

Bessere Lösung als angenommene Antwort! – mes