在postgresql中通过max(col)获取行过滤

时间:2016-09-28 13:11:28

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

我正在使用postgresql而且我对它不熟悉。这段代码有效,但我想知道我是否可以用更简单的方式编写它。在这里,我加入了bar,在子查询中加入吧。我希望有一些像select * from bar group by baz using max(z)

这样简单的东西
select *
from foo f
join bar b on(f.baz=b.baz AND b.z in (select max(z) from bar group by baz))
where uid1 = 120

3 个答案:

答案 0 :(得分:2)

只需使用<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" targetNamespace="http://tempuri.org/"> <xs:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/> <xs:element name="Cancel_OrderLineReq"> <xs:complexType> <xs:sequence> <xs:element name="Data"> <xs:complexType> <xs:sequence> <xs:element name="Delivery" maxOccurs="unbounded" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element type="xs:int" name="Delivery_No"/> <xs:element type="xs:string" name="Reason"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

distinct on

答案 1 :(得分:1)

@Gordon's answer几乎但不太正确。如果列可以是max(b.z),则ORDER BY b.z DESCNULL之间会有细微差别。经常被忽视并引起很多头痛。

即使列b.z已定义NOT NULL ,也可能会让您感到愤怒。外连接可以为列引入NULL值。在这个简单的查询中不会有效,但可以在更复杂的查询中。

虽然汇总功能如minmaxcount 忽略 NULL值,但ORDER BY子句中使用相同的列时,必须以某种方式处理 在默认排序顺序NULL值中排序最后。当排序顺序与DESC相反时,NULL值会先排序 。一定要保持一致。
因此,如果baz IS NULL中的任何DISTINCT ON值位于对等体集中,则从NULL获得max(b.z)行,其中您将从{{获得最大的非空值(如果有) 1}}。很可能不是你想要的。您可以使用 NULLS LAST

进行修复

另外,在使用SELECT *时,您不希望两次返回连接列baz - 保证相同。 USING子句派上用场,它只返回列一次

所以:

SELECT DISTINCT ON (baz) *
FROM   foo f
JOIN   bar b USING (baz)
WHERE  uid1 = 120   -- where from?
ORDER  BY baz, b.z DESC NULLS LAST;
即使没有NULLS LAST值,

NULL也不会受到伤害 - 除非您确实希望NULL值占上风。

DISTINCT ON的详细说明:

更快

由于uid1来自bazas commented),因此对于大型表格,此查询通常更快:

SELECT *
FROM   foo f
JOIN  (
   SELECT DISTINCT ON (baz) *
   FROM   bar
   WHERE  uid1 = 120
   ORDER  BY baz, z DESC NULLS LAST
   ) b USING (baz);

根据表定义和数据分布,可能会有更快的查询技术:

答案 2 :(得分:0)

嗨,您可以进行以下查询,

SELECT * FROM foo f
INNER JOIN (SELECT baz, MAX(z) FROM bar GROUP BY baz) b
ON (f.baz = b.baz)
WHERE f.uid1 = 120;

只需使用MAX(z)连接条形并填充所需的值。 uid1必须来自foo表,因为f用作别名,如果没有更改为b.uid1