2010-08-19 56 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)