use*_*817 5 sql postgresql join greatest-n-per-group sql-limit
我有以下查询:
SELECT sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount, 'rma' as
"creditType", "Clients"."company" as "client", "Clients".id as "ClientId", "Rmas".*
FROM "Rmas" JOIN "EsnsRmas" on("EsnsRmas"."RmaId" = "Rmas"."id")
JOIN "Esns" on ("Esns".id = "EsnsRmas"."EsnId")
JOIN "EsnsSalesOrderItems" on("EsnsSalesOrderItems"."EsnId" = "Esns"."id" )
JOIN "SalesOrderItems" on("SalesOrderItems"."id" = "EsnsSalesOrderItems"."SalesOrderItemId")
JOIN "Clients" on("Clients"."id" = "Rmas"."ClientId" )
WHERE "Rmas"."credited"=false AND "Rmas"."verifyStatus" IS NOT null
GROUP BY "Clients".id, "Rmas".id;
Run Code Online (Sandbox Code Playgroud)
问题是表"EsnsSalesOrderItems"可以EsnId在不同的条目中具有相同的表.我想将查询限制为仅拉取"EsnsSalesOrderItems"具有相同的最后一个条目"EsnId".
"最后"条目我指的是以下内容:
表中最后出现的那个"EsnsSalesOrderItems".因此,例如,如果"EsnsSalesOrderItems"有两个条目和"EsnId" = 6和"createdAt" = '2012-06-19','2012-07-19'它们应该只给我输入'2012-07-19'.
Erw*_*ter 15
SELECT (count(*) * sum(s."price")) AS amount
, 'rma' AS "creditType"
, c."company" AS "client"
, c.id AS "ClientId"
, r.*
FROM "Rmas" r
JOIN "EsnsRmas" er ON er."RmaId" = r."id"
JOIN "Esns" e ON e.id = er."EsnId"
JOIN (
SELECT DISTINCT ON ("EsnId") *
FROM "EsnsSalesOrderItems"
ORDER BY "EsnId", "createdAt" DESC
) es ON es."EsnId" = e."id"
JOIN "SalesOrderItems" s ON s."id" = es."SalesOrderItemId"
JOIN "Clients" c ON c."id" = r."ClientId"
WHERE r."credited" = FALSE
AND r."verifyStatus" IS NOT NULL
GROUP BY c.id, r.id;
Run Code Online (Sandbox Code Playgroud)
您在问题中的查询对另一个聚合具有非法聚合:
sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount
Run Code Online (Sandbox Code Playgroud)
简化并转换为合法语法:
(count(*) * sum(s."price")) AS amount
Run Code Online (Sandbox Code Playgroud)
但是你真的想要乘以每组的数量吗?
我检索每个组单列"EsnsSalesOrderItems"带DISTINCT ON.详细说明:
我还添加了表别名和格式,以便查询更容易解析人眼.如果你可以避免驼峰的情况下,你可以摆脱所有的双引号阴影视图.
就像是:
join (
select "EsnId",
row_number() over (partition by "EsnId" order by "createdAt" desc) as rn
from "EsnsSalesOrderItems"
) t ON t."EsnId" = "Esns"."id" and rn = 1
Run Code Online (Sandbox Code Playgroud)
这将选择最新的“ EsnId"从"EsnsSalesOrderItems"基于列creation_date。当你没有张贴你的表的结构,我不得不‘发明’列名。您可以使用允许您定义的行发出命令列适合你。
但是请记住,“最后一行”的概念仅在您指定订单或行时才有效。除非您指定一个表,否则这样的表是不排序的,查询的结果也不是order by
死灵术是因为答案已经过时了。
利用PG 9.3LATERAL中引入的关键字
左| 对| 内部连接横向
我将用一个例子来解释:
假设您有一个表“联系人”。
现在联系人有了组织单位。
他们在某个时间点可以有一个 OU,但在 N 个时间点可以有 N 个 OU。
现在,如果您必须查询某个时间段(不是报告日期,而是日期范围)内的联系人和 OU,如果您只执行左连接,则可以将记录数增加 N 倍。
因此,要显示 OU,您只需加入每个联系人的第一个 OU(其中第一个是任意标准 - 例如,当采用最后一个值时,这只是排序时表示第一个值的另一种方式按日期降序排列)。
在 SQL-server 中,您将使用交叉应用(或者更确切地说是外部应用,因为我们需要左连接),这将在它必须连接的每一行上调用一个表值函数。
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
-- CROSS APPLY -- = INNER JOIN
OUTER APPLY -- = LEFT JOIN
(
SELECT TOP 1
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(@in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(@in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
) AS FirstOE
Run Code Online (Sandbox Code Playgroud)
在 PostgreSQL 中,从版本 9.3 开始,您也可以这样做 - 只需使用LATERAL关键字即可实现相同的效果:
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
LEFT JOIN LATERAL
(
SELECT
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
LIMIT 1
) AS FirstOE
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17663 次 |
| 最近记录: |