如何对ID字段进行分组,并在另一个字段PostgreSQL中选择具有最高值的行

时间:2014-08-13 11:50:50

标签: sql postgresql greatest-n-per-group

我不知道我应该为问题提供标题 (更别提了)。 下面给出的是我的选择查询

select gtab04.product,gtab05.productid,gtab05.mrp, gtab05.ptr,gtab05.ssr,gtab07.patent from gtab05 inner 
join gtab07 on gtab05.patentid=gtab07.patentid inner join gtab04 on 
gtab05.productid=gtab04.productid  where gtab05.qty-gtab05.iqty > 0 order by productid

这将返回500+行,请参阅以下示例

product           |productid   |mrp     |ptr  |ssr  |patent
------------------+------------+--------+-----+-----+----------------- 
IBUGESIC Plus Tab |200         |12.80000|9.85 |8.87 |CIPLA LTD 
ANGICAM 2.5 Tab   |267         |9.00000 |6.93 |6.44 |BLUE CROSS LABORATORIES 
ANGICAM 2.5 Tab   |267         |5.00000 |6.93 |6.24 |BLUE CROSS LABORATORIES 
ANGICAM 2.5 Tab   |267         |5.00000 |6.93 |6.44 |BLUE CROSS LABORATORIES 
ANGICAM 2.5 Tab   |267         |5.00000 |7.359|6.24 |BLUE CROSS LABORATORIES 
ANGICAM 5 Mg Tab  |268         |14.00000|10.78|10.03|BLUE CROSS LABORATORIES 
ANGICAM 5 Mg Tab  |268         |12.00000|11.44|9.7  |BLUE CROSS LABORATORIES 
ANGICAM BETA Tab  |269         |17.00000|13.09|12.17|BLUE CROSS LABORATORIES 
ANGICAM BETA Tab  |269         |15.00000|13.9 |11.78|BLUE CROSS LABORATORIES 
HIBESOR 25 TAB    |270         |9.00000 |6.93 |6.44 |BLUE CROSS LABORATORIES 

我想修改上面的结果,如下所示..

product           |productid   |mrp     |ptr  |ssr  |patent
------------------+------------+--------+-----+-----+----------------- 
IBUGESIC Plus Tab |200         |12.80000|9.85 |8.87 |CIPLA LTD 
ANGICAM 2.5 Tab   |267         |9.00000 |6.93 |6.44 |BLUE CROSS LABORATORIES 
ANGICAM 5 Mg Tab  |268         |14.00000|10.78|10.03|BLUE CROSS LABORATORIES 
ANGICAM BETA Tab  |269         |17.00000|13.9 |11.78|BLUE CROSS LABORATORIES 
HIBESOR 25 TAB    |270         |9.00000 |6.93 |6.44 |BLUE CROSS LABORATORIES 
  • 我的标准:需要 GROUP productid以及来自每个product拥有max(mrp)

我迄今为止所尝试过的。

    With cte as (
    select gtab04.product,gtab05.productid,gtab05.mrp, gtab05.ptr,gtab05.ssr,patent from gtab05 
    inner join gtab07 on gtab05.patentid=gtab07.patentid inner join gtab04 on 
    gtab05.productid=gtab04.productid  where qty-iqty > 0 order by productid limit 10
    )
    select productid,max(cte.mrp) as mrp  from cte group by productid order by  productid
    )

         RESULT
    --------------
   productid | mrp
          200|12.80000
          267|9.00000
          268|14.00000
          269|17.00000
          270|9.00000

3 个答案:

答案 0 :(得分:1)

distinct on结合order by

select distinct on (productid) 
    gtab04.product,
    productid,
    gtab05.mrp,
    gtab05.ptr,
    gtab05.ssr,
    patent
from
    gtab05
    inner join
    gtab07 using(patentid)
    inner join
    gtab04 using(productid)
where qty-iqty > 0
order by productid, gtab05.mrp desc

如果有任何其他解开标准,请将其添加到order by子句

http://www.postgresql.org/docs/current/static/sql-select.html#SQL-DISTINCT

答案 1 :(得分:0)

重用原来的CTE:

WITH cte AS (
    select gtab04.product
       ,gtab05.productid ,gtab05.mrp, gtab05.ptr, gtab05.ssr
       ,patent -- NEEDS alias-designation
    from gtab05 
    inner join gtab07 on gtab05.patentid = gtab07.patentid -- NOT USED ...
    inner join gtab04 on gtab05.productid = gtab04.productid
    where qty-iqty > 0 -- NEEDS alias-designation
    order by productid -- NEEDS alias-designation
    -- limit 10
    )
SELECT * FROM cte t0
WHERE NOT EXISTS (
   SELECT * FROM cte t1
   WHERE t1.productid = t0.productid
   AND t1.mrp > t0.mrp
   )
order by  productid
   ;

答案 2 :(得分:0)

在澄清问题之后,我认为这种变体应该更快地执行:

SELECT g4.product, g5.productid, g5.mrp, g5.ptr, g5.ssr, g7.patent
FROM  (
   SELECT DISTINCT ON (productid)
          productid, mrp, ptr, ssr, patentid
   FROM   gtab05
   WHERE  qty > iqty
   ORDER  BY productid, mrp DESC
   ) g5
JOIN   gtab07 g7 USING (patentid)
JOIN   gtab04 g4 USING (productid);

基本上它使用DISTINCT ON,例如@Clodoaldo already provided。详细解释:

改变了两件事:

  • 在加入更多表格之前消除重复数据更便宜。利益随着每组的行数而增加。我假设,加入gtab07gtab04不会产生更多重复项。

  • WHERE条件可简化为WHERE qty > iqty。稍微短一些 但是, if 条件是选择(小于表限定的约5%),并且你必须经常运行这个查询(并且增益超过了索引维护),然后保持原始状态并使用functional index

    支持它
    CREATE INDEX gtab05_qty_iqty_idx ON gtab05((qty - iqty));
    

运行EXPLAIN ANALYZE以测试效果。