如何编写一个选择合理权衡的查询?

时间:2011-04-15 21:30:31

标签: mysql sql select

在表格中我有两列obs和abd。我有兴趣找到 obs和abd的值都很低,但是abd的值较低 比blind值低的重要。在现实世界中,我有一个 低障碍和低障碍之间的权衡,这是不容易定义的 在数学上并且很难解释,但重点是 我想从查询中看到的是一些可以产生的数据 合理的权衡取舍。我想知道一个中的几个数据对 范围的障碍值。例如:

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 |
    +------+--------------+

从以上结果可以看出,有几个值 具有相同abd值的obs。我只对那个感兴趣 每个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          |
+------+--------------+
| 1372 | 0.0000004744 |
| 1010 | 0.0000017716 |
|  383 | 0.0000066084 |
+------+--------------+

加上另外七个条目,其中obs继续减少和abd 继续增加。有没有办法获得一组数据对 一个查询而不诉诸程序?

2 个答案:

答案 0 :(得分:1)

要按obs获得最低abd,请按以下步骤操作:

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

但在我看来,权衡规则是一种临时性的。您应该尝试找出您能想到的最佳规则,并将它们放在桌面上,以便我们能够实现您的目标。

答案 1 :(得分: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上有索引,我猜第四个。或者更好,(正如Unreason指出的那样),两个索引:一个在(obs, abd)上,另一个在abd上。


更新: (第3次查询的小修正)。