2010-09-17 39 views
2

我對正確的查詢有一些疑問,希望您能幫助我。我的測試表結構如下:SQL - 通過其他表中的值對項目進行排序的正確查詢

CREATE TABLE IF NOT EXISTS `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(45) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
) ; 

CREATE TABLE IF NOT EXISTS `user_throws` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_id` int(11) NOT NULL, 
    `length` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`,`user_id`), 
) ; 

它們之間的關係是多對一(一個用戶可以有很多罰球)。事情是我需要爲所有用戶創造一個類似排名的頁面,比如說排名前100的投手。所以我需要一個查詢結果爲:

  1. 由用戶篩選,所以只有有任何投擲和投擲長度大於0的用戶是正確的記錄。
  2. 按重複過濾,因此只有唯一的用戶出現在列表中(GROUP BY我想)。
  3. 按投擲長度排序,因此只會追加最好(最大)的結果。

爲此我寫的查詢:

SELECT `user_throws`.`length` , `users` . * 
FROM `users` 
JOIN `user_throws` ON ( `user_throws`.`user_id` = `users`.`id`) 
WHERE `user_throws`.`length` > '0' 
GROUP BY `users`.`id` 
ORDER BY `user_throws`.`length` DESC 

但問題是結果不是由最長投射排序。它過濾長度大於0的拋出並顯示唯一的用戶,但附加的長度不符合所需的排序。我發現length的價值是最低價投擲user_throws。與用戶關聯的id。正確的查詢應該如何?

回答

1

嘗試:

SELECT longthrow,id,name FROM (
SELECT max(t.length) longthrow,u.id,u.name 
FROM users u, user_throws t 
WHERE u.id=t.user_id 
AND t.length>0 
GROUP BY u.id 
) ORDER BY longthrow DESC 

這應該給你的每個用戶的最長投射,由最遠擲排序第一,最短的最後 - 認爲這是你想要的東西;)

而且我前應加評論顯示,這是更好地與啓動:

SELECT max(t.length) longthrow,u.id,u.name 

比:

SELECT max(t.length) longthrow,u.* 
+0

該理論很好,但這不會完全奏效,因爲除非您還有GROUP BY這些字段,否則您不能選擇帶有MAX聚合子句的u。*。如果你調整它應該工作的語法。 – 2010-09-17 16:09:32

+0

實際上,也許不幸的是,這在MySQL中執行得很好......這些怪癖之一;) – Rudu 2010-09-17 16:10:53

+0

這是真的MAX()將做最大的結果選擇,但不會以最長的投擲長度排序用戶。所以這不完全是我正在尋找的。不管怎麼說,還是要謝謝你。 – 2010-09-17 16:32:29

0

如何

SELECT MAX(`user_throws`.`length`) , `users` . * 
... 
+0

理論很好,但這不會完全奏效,因爲您無法選擇用戶。*帶有MAX聚合子句,除非您還有GROUP BY這些字段。如果你調整它應該工作的語法。 – 2010-09-17 16:10:02

+0

這是真的MAX()將做最大的結果選擇,但不會以最長的投擲長度排序用戶。所以這不完全是我正在尋找的。不管怎麼說,還是要謝謝你。 – 2010-09-17 16:35:44

0

group by

SELECT `user_throws`.`length` , `users` . * 
FROM `users` 
JOIN `user_throws` ON ( `user_throws`.`user_id` = `users`.`id`) 
GROUP BY `users`.`id` 
HAVING `user_throws`.`length` > 0 
ORDER BY `user_throws`.`length` DESC 

編輯後添加having子句:我現在看到,這是不是你要找的東西。您正在尋找每位用戶的最佳投注。其他一些答案更適用。

+0

having子句只是重複where子句並且不會產生最長的拋出。您需要使用MAX聚合函數。 – 2010-09-17 16:11:59

0

你可以嘗試一個子查詢解決方案,它看起來是這樣的:

SELECT 
     (SELECT MAX(length) FROM user_throws WHERE user_id=users.id) AS LongThrow, 
     users.* 
    FROM users 
    WHERE (SELECT MAX(length) FROM user_throws WHERE user_id=users.id) > '0' 
    ORDER BY (SELECT MAX(length) FROM user_throws WHERE user_id=users.id) 

注:語法是從我的頭頂......請帶一粒鹽。另外,上面的查詢是非常冗長的,但應該沒有問題。您可以按照您認爲合適的方式將其縮寫。

但無論如何,子查詢的想法將工作。你可能只需要調整/播放語法。

+0

我想盡可能避免子查詢。因此,在一個查詢中執行該操作是期望的解決方案(我認爲這是可能的)。 – 2010-09-17 16:35:18

+0

@Karol:子查詢可以成爲你的朋友。如果您的表索引完成並且查詢優化得當,它們可以很好地工作。但如果受到虐待,他們也會受到傷害。我看到的唯一可能的麻煩是如果你的user_throws.user_id fkey沒有被索引。無論如何,我會嘗試一下。應該只需要一分鐘。 – 2010-09-17 17:03:19

0

嘗試

SELECT u2.`length` , u . * 
FROM `users` u , `user_throws` u2 where u2.`user_id` = u.`id` 
AND u2.`length` > '0' and u2.`id` = (select u1.id from `user_throws` u1 where u1.`user_id` = u.id order by u1.`length` desc limit 1) 
GROUP BY u2.`user_id` 
0
SELECT `user_throws2`.`length` , `users` . * 
FROM `users` 
JOIN (SELECT * FROM user_throws ORDER BY length DESC) as user_throws2 
    ON ( `user_throws2`.`user_id` = `users`.`id`) 
WHERE `user_throws2`.`length` > '0' 
GROUP BY `users`.`id` 
ORDER BY `user_throws2`.`length` DESC 

試試吧,去年MySQL的工作(如果你不工作,MySQL的更新是:d)

0

稍微不同的方法:

select ut.longest, u.id, u.name 
from users u 
join 
(select user_id, max(length) longest 
from user_throws 
where length > 0 
group by user_id) ut on u.id = ut.user_id 
order by ut.longest desc 
0

SELECT MAX(user_throws.length),用戶。 * FROM用戶加入user_throws ON(user_throws.user_id = users.id)WHERE user_throws.length> 0 GROUP BY users.id ORDER BY user_throws.length DESC

我嘗試,它的作品,只是檢查執行時間對於這兩個選項

相關問題