Mysql - 加入2个限制的查询

Mysql - 加入2个限制的查询

问题描述:

我不太熟悉在查询中使用'join'。我真的试过自己解决这个问题,但似乎太难了。Mysql - 加入2个限制的查询

我有2个表:

Table 'users': 
+-----------------+-----------------+ 
|  member  |  online  | 
+-----------------+-----------------+ 
| mahran   |    1 | 
| peter   |    1 | 
| Jen    |    1 | 
| Steve   |    0 | 
+-----------------+-----------------+ 

Table 'tickets' 
+-----------------+----------------+----------------+ 
|  name  | category |  time  | 
+-----------------+----------------+----------------+ 
| mahran   | silver   |    1 | 
| peter   | blue   |    1 | 
| mahran   | blue   |    2 | 
| peter   | red   |    3 | 
| peter   | green   |    2 | 
| Jen    | silver   |    1 | 
+-----------------+----------------+----------------+ 

的chellange:
我需要每个成员(users.member)谁在线(users.online)。接下来的事情是用最高时间(可能是ORDER BY time DESC LIMIT 1)获取每个成员的类别(user.member = tickets.name)。

因此,例如: Peter在线。彼得斯最高时间在红色类别的位置是3。所以我希望彼得以“红色”的分类出现在结果中。马赫兰会出现蓝色。仁会得到银子。史蒂夫因为不在线而被拒之门外。

我希望这很清楚。一般来说,我知道查询的样子是怎样的,但是我没有机会将它们合并在一起。

有什么需要合并:

SELECT member FROM users WHERE online = 1; 
| 
v for each member 
SELECT category FROM tickets WHERE name=users.member ORDER BY time DESC. 

因此,任何想法如何解决这个问题?

这里是一个没有工作的查询小提琴:Click

+0

加入会员不是一个好主意。使用主键和外键。 – 2014-09-03 10:37:09

这里是你要找的查询:

SELECT U.member 
    ,T.category 
FROM users U 
INNER JOIN tickets T ON T.name = U.member 
INNER JOIN (SELECT T2.name 
       ,MAX(T2.time) AS [maxTime] 
      FROM tickets T2 
      GROUP BY T2.name) AS M ON M.name = T.name 
           AND M.maxTime = T.time 
WHERE U.online = 1 

使用[名]的加入两个表是不是一个好的做法,这是好多了改为使用键。但我的查询只是为了帮助您了解合作过程。

希望这会帮助你。

+0

解决了我的问题,也解决了最快的处理查询(使用超过50k条目的数据库时不重要)。谢谢。 – C4u 2014-09-03 11:03:13

+0

@ C4ud3x感谢您对性能的反馈,我知道这是一个差异,但速度快两倍!原因很容易理解,通过合作关系,您只能获得每个成员的最大值一次,而不是每次查询表中的一行。 – 2014-09-03 11:05:36

+0

是的,我也对处理时间感到惊讶。戈登的解决方案耗时约24ms,仅用12ms(多次测试),通过使用带55600个条目的票据表。感谢您详细解释。我只是想进入我的查询使用加入。 – C4u 2014-09-03 11:21:12

如果我理解正确

SELECT DISTINCT users.member, tickets.category FROM tickets JOIN users ON users.member = tickets.name WHERE users.online = 1 ORDER BY tickets.time DESC 
+0

有了这个,我得到了同样的成员多次出现。我只想在每个成员的最高时间只显示一次他的类别。 – C4u 2014-09-03 10:39:06

+0

我建立了一个表的小提琴。应该更容易。 – C4u 2014-09-03 10:41:34

您可以使用相关子查询做到这一点很容易:

select u.member, 
     (select t.category 
     from tickets t 
     where t.name = u.member 
     order by t.time desc 
     limit 1 
     ) as MostRecentCategory 
from users u 
where u.online = 1; 

这可以使用以下索引:users(online, member)ticket(member, time, category)

+0

完美的作品。非常感谢。 – C4u 2014-09-03 10:50:27

+1

它正在工作,但在性能方面,它不是最优的,你的子查询将被执行表中的每一行[用户] – 2014-09-03 10:51:55

+0

@JoëlSalamin:我检查了性能。你是对的。您的查询速度提高了两倍。更改了解决方案标记。 – C4u 2014-09-03 11:02:01

你可以做sql小提琴吗?

USE DISTINCT 

*.com/questions/11704012/mysql-distinct-join

试试这个

SELECT DISTINCT User.member,Ticket.category FROM users AS USER 
INNER JOIN tickets AS Ticket ON (User.member = Ticket.name) 
WHERE User.online = 1; 
+0

会员多次出现。 – C4u 2014-09-03 10:52:03

+0

我已编辑我的答案 – deadman 2014-09-03 10:55:51

+0

它输出孔表'门票'。检查我发布在问题底部的小提琴,并尝试自己的查询。 – C4u 2014-09-03 10:59:16

抱歉,彼得好像是红色的,它的时间是3。不是吗?

根据表定义,不保证每个用户只有一个结果。 例如,如果peter在两个类别中有时间3,则可以根据SQL排序方法获得一个不同的类别。

可以肯定,tickets.Category和门票。时间必须在一个唯一的密钥(都是,不是每个字段的唯一键)

假设,查询可能是这样的。

select t2.name, t2.category 
from 
tickets t2 
INNER JOIN (Select 
     u.member, max(time) 
     from users u, tickets t 
     where 
     u.member = t.name 
     and u.online = 1 
     group by u.member 
     ) as usermaxtime on t2.name = usermaxtime.member; 
+0

避免使用这种老派的语法将两个表连接在一起,请使用'INNER'子句 – 2014-09-03 11:07:21

+0

我的错,很抱歉。当然,彼得类别应该显示为红色。乔尔的解决方案仍然正确。 – C4u 2014-09-03 11:14:30

+0

请确保我的评论关于两个或更多类别在同一个成员上的同一时间。 – Biggum 2014-09-03 11:19:01