2014-09-03 125 views
0

我不太熟悉在查詢中使用'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

回答

1

這裏是你要找的查詢:

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

0

如果我理解正確

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

2

您可以使用相關子查詢做到這一點很容易:

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

0

試試這個

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

-1

抱歉,彼得好像是紅色的,它的時間是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