选择组中具有第二高的值的行

时间:2019-06-03 16:02:57

标签: postgresql aggregate-functions

我有一个这样的表(tbl):

+----+-----+------+-----+
| pk | grp | attr | val |
+----+-----+------+-----+
|  0 |   0 | ohif |   4 |
|  1 |   0 | foha |  56 |
|  2 |   0 | slns |   2 |
|  3 |   1 | faso |  11 |
|  4 |   1 | tepj |   4 |
|  5 |   2 | bnda |  12 |
|  6 |   2 | ojdf |   9 |
|  7 |   2 | anaw |   1 |
+----+-----+------+-----+

我想从每个组中选择一行,尤其是每个组中val第二高的行。

即,我想要这张桌子:

+----+-----+------+-----+
| pk | grp | attr | val |
+----+-----+------+-----+
|  1 |   0 | ohif |   4 |
|  3 |   1 | tepj |   4 |
|  5 |   2 | ojdf |   9 |
+----+-----+------+-----+

这是我想出的解决方案:

SELECT DISTINCT ON (grp)
pk,
(
    SELECT innertbl.grp
    FROM tbl AS innertbl
    WHERE innertbl.grp = tbl.grp
    ORDER BY innertbl.val DESC
    LIMIT 1 OFFSET 1
) AS grp,
(
    SELECT innertbl.attr
    FROM tbl AS innertbl
    WHERE innertbl.grp = tbl.grp
    ORDER BY innertbl.val DESC
    LIMIT 1 OFFSET 1
) AS attr,
(
    SELECT innertbl.val
    FROM tbl AS innertbl
    WHERE innertbl.grp = tbl.grp
    ORDER BY innertbl.val DESC
    LIMIT 1 OFFSET 1
) AS val
FROM tbl

但这是低效率的,因为它需要为每个组的每个列选择一个子查询。

我在使用Postgres 10。

2 个答案:

答案 0 :(得分:1)

您可以在子查询中使用窗口函数来获取所需的内容:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="primary-navigation">
  <ul id="menu-main-navigation" class="menu nav-menu">

    <li id="menu-item-428" class="main-nav-item-1">
      <a href="https://link-1.com">Link-1</a></li>

    <li id="menu-item-344" class="main-nav-item-2">
      <a href="https://link-2.com">Link-2</a></li>

    <li id="menu-item-228" class="main-nav-item-3">
      <a href="https://link-3.com">Link-3</a></li>
      
    <li class="underline-border"></li>
  </ul>
</div>

row_number()提供了该组内的一个序列(使用PARTITION BY)。

答案 1 :(得分:0)

@Nick的答案是我要发布的内容,但是要说一件事,如果您想跳过重复项,可以使用dense_rank函数:

SELECT pk, grp, attr, val FROM (
  SELECT
    *,
    DENSE_RANK() OVER (PARTITION BY grp ORDER BY val DESC) AS seqnum
  FROM
    mytable
) t WHERE seqnum = 2;