2014-11-21 34 views
8

W PostgreSQL 9 na CentOS 6 istnieje 60000 rekordy w pref_users tabeli:Lewe sprzężenie zewnętrzne - jak zwrócić wartość boolean do istnienia w drugiej tabeli?

# \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...) 

I kolejna tabela posiada około 500 identyfikatory użytkowników, którzy nie mogą już grać:

# \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) 

W PHP Skrypt próbuję wyświetlić wszystkie 60000 użytkowników od pref_users w jQuery-dataTable. I chciałbym zaznaczyć zbanowanych użytkowników (użytkowników znalezionych w pref_ban2).

Co oznacza, że ​​potrzebuję kolumny o nazwie ban dla każdego rekordu w moim zapytaniu z numerem true lub false.

Więc staram się lewe sprzężenie zewnętrzne zapytanie:

# 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) 

Jak widać kolumna b.id powyżej jest pusty - bo te 10 użytkowników nie są zakazane.

Jak uzyskać wartość false w tej kolumnie zamiast ciągu?

I nie jestem po wyrażeniu coalesce lub case, ale szukam "właściwego" sposobu na wykonanie takiego zapytania.

Odpowiedz

8

Instrukcja CASE lub COALESCE z łączeniem zewnętrznym jest właściwym sposobem wykonania tej czynności.

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

Dziękuję za odpowiedź, ale czy nie powinienem (lepiej) używać tutaj słowa "istnieje"? –

+0

Więc 'EXISTS' działa jak filtr. Jeśli użyjesz 'EXISTS', po prostu nie otrzymasz rekordu, jeśli zostanie odfiltrowany. Jeśli chcesz wyświetlić wartość 'boolean', lepiej będzie z" CASE ". –

+0

Do tego momentu możesz użyć 'EXISTS' zamiast' OUTER JOIN', ale to nie zmieni logiki boolowskiej. –

3

"IS NULL" i "IS NOT NULL" zwracają wartość boolean, więc powinno to ułatwić.

Myślę, że to wszystko, czego potrzebujesz?

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

Nie jestem pewien, czy potrzebujesz "NIE", czy nie, ale otrzymasz bool tak czy inaczej.

+0

Lepsze rozwiązanie niż zaakceptowana odpowiedź! – mes