2010-08-19 105 views
2

我正在寫一個管理註冊到關聯的人的小工具。SQL:一對多,只選擇一個

我有一個表USERS和一個表CARDS。每個用戶可以有多張卡片(因爲卡片到期)。

有一個查詢,我想提取所有用戶信息加上所有卡信息只適用於最新的卡(字段:ISSUEDATE)。

這是一個非常簡單的例子:

USERS表

IDUSER NAME SURNAME 
------------------------ 
1  Robert Hill 

牌桌

IDCARD IDOWNER ISSUEDATE DESC 
---------------------------------------- 
1  1  2010-01-01 'CARD ONE' 
2  1  2010-08-18 'CARD TWO' 

基本上我想從我的查詢這些字段後面:

IDUSER NAME  SURNAME IDCARD IDOWNER ISSUEDATE DESC 
--------------------------------------------------------------- 
1  Robert Hill  2  1  2010-08-18 'CARD TWO' 

我試過,但我不能管理:(

編輯: 如果有鏈接到用戶無卡,會發生什麼? (一位用戶已經註冊,但該協會尚未給他/她任何卡)。無論如何,有什麼辦法來調整這個查詢以獲取用戶信息?這個想法是爲每個用戶獲取所有可能的信息。此信息稍後將在廣告ExtJS應用程序上通過JSON使用。

感謝您的回答。

+0

按照堆棧溢出中的其他幾十個類似問題的'greatest-n-per-group'標籤。 – 2010-08-19 20:55:51

+0

「如果沒有與用戶關聯的無卡,會發生什麼?」你想要發生什麼?無法返回任何記錄,或者來自CARDS表的記錄字段可能設置爲NULL。 – strager 2010-08-20 06:23:20

+0

是的,我的編輯不清楚,對不起。最好的辦法是爲所有CARDS列獲得一組NULL值,以防用戶還沒有任何卡。 – Danilo 2010-08-20 06:29:19

回答

1

選項1與NOT EXISTS查詢:

select u.IDUSER, u.NAME, u.SURNAME, 
     c.IDCARD, c.IDOWNER, c.ISSUEDATE, c.DESC 
from USERS u 
join CARDS c on u.IDUSER = c.IDOWNER 
where not exists (select 1 from CARDS where IDOWDER = u.IDUSER and ISSUEDATE > c.ISSUEDATE) 

選項2與LIMIT

select u.IDUSER, u.NAME, u.SURNAME, 
     c.IDCARD, c.IDOWNER, c.ISSUEDATE, c.DESC 
from USERS u 
join CARDS c on u.IDUSER = c.IDOWNER 
order by c.ISSUEDATE desc 
LIMIT 1 
1
select u.IDUSER, u.NAME, u.SURNAME, 
     c.IDCARD, c.IDOWNER, c.ISSUEDATE, c.DESC 
from USERS u 
join CARDS c on u.IDUSER = c.IDOWNER and c.IDCARD in (
    /* select biggest IDCARD numbers that has same IDOWNER thus eliminating multiple rows and remaining only 1 for each IDOWNER */ 
    select MAX(IDCARD) as IDCARD 
    from USERS join CARDS on USERS.IDUSER = CARDS.IDOWNER 
    group by CARDS.IDOWNER 

) 
+0

爲什麼在IN子句中加入select? '通過CARDS.IDOWNER'選擇MAX(IDCARD)作爲IDCARD組應該足夠了。 – 2013-05-01 17:30:00

1

本書雖然LIMIT通常不alowed在MySQL子查詢,LIMIT 1是一個例外,所以 「選擇一個「對於這種情況來說是完美的。

LEFT JOIN確保了你也會有不帶存儲卡的數據用戶(卡內的數據將是NULL,您可以使用ifnull(desc, 'No Card Issued'),以顯示你的意志)

和子查詢確保只有用戶最近的卡數據將被選中。

SELECT * 
    FROM users u 
     LEFT JOIN cards c 
     ON c.idcard = (SELECT idcard 
          FROM cards c1 
         WHERE c1.idowner = u.iduser 
         ORDER BY issuedate DESC 
         LIMIT 1)