2016-05-13 75 views
0

有行,如:PostgreSQL的選擇兩個頂部城鎮

user | town 1 | town 2 | town 3 | town 4 | town 5 | town 6| 

城鎮都有整數值,其中鎮3鎮4擁有最大數量

我想選擇的兩個頂部城鎮用戶因此最終的結果應該是:

user | town 3 | town 4 | 
+1

有了正確的標準化模型,這很容易。爲什麼你將這些信息存儲在多個列中?你爲什麼不把它變成適當的1:多關係 –

回答

2

這是正確的標準化模型:

create table users (
    user_id serial primary key, 
    user_name varchar(100) 
); 

create table town (
    town_id serial primary key, 
    town_int int 
); 

create table user_town (
    town_id int references town (town_id), 
    user_id int references users (user_id), 
    primary key (user_id, town_id) 
); 

insert into users (user_name) values ('John'); 
insert into town (town_int) values (1),(2),(3),(4),(5),(6); 
insert into user_town (user_id, town_id) values (1,1),(1,2),(1,3),(1,4),(1,5),(1,6); 

如何查詢它:

select user_id, user_name, town_id, town_int 
from 
    user_town 
    inner join 
    users using (user_id) 
    inner join 
    town using (town_id) 
where user_id = 1 
order by town_int desc 
limit 2 
; 
user_id | user_name | town_id | town_int 
---------+-----------+---------+---------- 
     1 | John  |  6 |  6 
     1 | John  |  5 |  5 
0

Somtimes我們剛纔我們所擁有的,例如窮人設計的傳統DB。然後

WITH t AS (
SELECT 100 as userid, 11 as town1, 23 as town2, 77 as town3, 14 as town4, 15 as town5, 16 as town6 
UNION ALL 
SELECT 101 as userid, 21 as town1, 235 as town2, 177 as town3, 24 as town4, 25 as town5, 26 as town6 
) 
SELECT userid, max(r.town) as top1, min(r.town) as top2 
FROM t 
CROSS JOIN LATERAL(
    SELECT town1 as town FROM t t2 WHERE t2.userid=t.userid 
    UNION ALL 
    SELECT town2 FROM t t2 WHERE t2.userid=t.userid 
    UNION ALL 
    SELECT town3 FROM t t2 WHERE t2.userid=t.userid 
    UNION ALL 
    SELECT town4 FROM t t2 WHERE t2.userid=t.userid 
    UNION ALL 
    SELECT town5 FROM t t2 WHERE t2.userid=t.userid 
    UNION ALL 
    SELECT town6 FROM t t2 WHERE t2.userid=t.userid 
    ORDER BY town DESC LIMIT 2) AS r 
GROUP BY userid;