2011-04-15 40 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

相关问题