2011-04-15 49 views
2

在表中我有兩列obs和abd。我有興趣爲obs和abd找到 較低的值,但對於obs來說,較低的值對於abd更重要。在現實世界中,我有一個 在低obs和低abd之間進行折衷,這在數學上不容易定義 ,並且很難解釋,但要點是我想從查詢中看到的是一些數據將使 合理的權衡。我想知道一個 範圍內的obs值的幾個數據對。例如:如何編寫一個查詢選擇合理的權衡?

mysql> select obs, abd from flow where obs < 2000 order by abd,obs limit 10; 

    +------+--------------+ 
    | obs | abd   | 
    +------+--------------+ 
    | 1372 | 0.0000004744 | 
    | 1734 | 0.0000017704 | 
    | 1010 | 0.0000017716 | 
    | 1999 | 0.0000017716 | 
    | 1637 | 0.0000036486 | 
    | 383 | 0.0000066084 | 
    | 745 | 0.0000066084 | 
    | 1107 | 0.0000066084 | 
    | 1469 | 0.0000066084 | 
    | 1831 | 0.0000066084 | 
    +------+--------------+ 

從上述結果,可以看出,有若干值OB的 具有相同ABD值。我只對每個abd值具有最低obs值的 感興趣。所有其他 重複的abd值應該被丟棄。這是很容易使用 GROUP BY子句來完成:

mysql> select obs, abd from flow where obs < 2000 group by abd order by abd,obs limit 10; 

    +------+--------------+ 
    | obs | abd   | 
    +------+--------------+ 
    | 1372 | 0.0000004744 | 
    | 1734 | 0.0000017704 | 
    | 1010 | 0.0000017716 | 
    | 1637 | 0.0000036486 | 
    | 383 | 0.0000066084 | 
    | 648 | 0.0000066096 | 
    | 1540 | 0.0000097586 | 
    | 1928 | 0.0000109544 | 
    | 1566 | 0.0000119724 | 
    | 913 | 0.0000119736 | 
    +------+--------------+ 

到目前爲止,一切都很好。現在的問題是,在看到第一個 條目,其中obs是1372,abd是0.0000004744之後,我對 看不到第二個條目,其中obs和abd都較高。我對 感興趣,看到obs較低但abd較高的第三項,因爲obs和abd之間存在權衡。再次,我 不想看到第四個條目,因爲它具有obs 和abd的值都比第三個 條目中已經顯示的值高。第五項是我特別感興趣的,因爲 儘管abd值稍高一些,但obs值卻低得多。 至於其餘的條目,我想看不到他們,因爲 他們有更高的obs和abd比已經看到。

總之,我想一個查詢,會告訴我:

+------+--------------+ 
| obs | abd   | 
+------+--------------+ 
| 1372 | 0.0000004744 | 
| 1010 | 0.0000017716 | 
| 383 | 0.0000066084 | 
+------+--------------+ 

加上地方OBS繼續下降和ABD 繼續增加其他七個條目。有沒有辦法讓一組數據對 與一個查詢,而不訴諸於程序?

回答

1

獲得最低obs通過abd,這裏是你如何去:

select min(obs), abd 
from flow 
where obs < 2000 
group by abd 
order by abd 

但似乎對我來說,權衡規則是一種特設的。你應該試着找出你能想到的最好的規則,然後把它們放在桌子上,這樣我們就可以實現你想要做的事情。

1

你可以只說你想要一個Pareto front

它不會是快,但試試這個:

SELECT a.obs 
    , a.abd 
FROM flow a 
    LEFT JOIN flow b 
    ON (b.obs <= a.obs AND b.abd < a.abd) 
     OR (b.obs < a.obs AND b.abd <= a.abd) 
WHERE b.obs IS NULL 
ORDER BY a.abd 

另外:

SELECT a.obs 
    , a.abd 
FROM flow a 
WHERE NOT EXISTS 
    (SELECT 1 
    FROM flow b 
    WHERE (b.obs <= a.obs AND b.abd < a.abd) 
     OR (b.obs < a.obs AND b.abd <= a.abd) 
) 
ORDER BY a.abd 

而且這樣的:

SELECT a.obs 
    , a.abd 
FROM flow a 
WHERE NOT EXISTS 
    (SELECT 1 
    FROM flow b 
    WHERE b.obs <= a.obs 
     AND b.abd < a.abd 
) 
    AND NOT EXISTS 
    (SELECT 1 
    FROM flow b 
    WHERE b.obs < a.obs 
     AND b.abd = a.abd 
) 
ORDER BY a.abd 

或這個:

SELECT a.obs 
    , a.abd 
FROM flow a 
WHERE NOT EXISTS 
    (SELECT 1 
    FROM flow b 
    WHERE b.obs <= a.obs 
     AND b.abd <= a.abd 
     AND (b.obs, b.abd) <> (a.obs, a.abd) 
) 
ORDER BY a.abd 

檢查4個哪個更快。如果你在obsabd上有索引,我會猜想第4個。或者更好,(如Unreason指出的),兩個索引:一個在(obs, abd)和一個在abd


更新: (在第3個查詢中的小修正)。

+1

甚至更​​快,如果有索引(obs,abd) – Unreason 2011-04-16 09:00:30

+0

也根據http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join -is-null-mysql /(這是簡單和不同的情況)左連接/爲空產生更好的計劃。 – Unreason 2011-04-16 09:04:42

+0

@不理由:是的,你是對的,(obs,abd)和(abd)上的一個索引在這裏可能是最好的。對於「左連接vs不存在」以及哪個產品最好的計劃,我只能相信真實數據的測試。我認爲數據分佈可能會對大型數據集產生影響。 – 2011-04-16 19:10:14

相關問題