对于这个复杂的查询,我有点不知所措。背景知识:这是一个Rails应用程序,我有一个expenditures
模型,其中有许多expenditure_items
,每个模型都有一个“金额”列-所有这些加起来总计为相关支出。
给定的expenditure
可以是一个订单,然后可以具有多个(或单个或零个)相关的发票expenditures
。我正在寻找一个查询,可以查询所有具有发票总额的订单,并确定那些发票总额超过阈值(在我的情况下为10%)的订单。我与此查询很接近:
SELECT DISTINCT "expenditures".* FROM "expenditures" JOIN expenditures AS invoices ON invoices.category = 'invoice' AND expenditures.id = CAST( invoices.ancestry AS INT) JOIN expenditure_items ON expenditure_items.expenditure_id = expenditures.id JOIN expenditure_items AS invoice_items ON invoice_items.expenditure_id = invoices.id WHERE "expenditures"."category" IN ($1, $2) GROUP BY expenditures.id HAVING (SUM( expenditure_items.amount ) > SUM( invoice_items.amount )) [["category", "work_order"], ["category", "purchase_order"]]
当我说“关闭”时,我得到的是我要查找的结果,只是它只捕获第一个相关发票。例子我回来了:
订单#1 $ 10,000 -1号发票$ 12,000 -发票#2 $ 1,000
问题似乎是SUM( invoice_items.amount )
仅返回$ 12,000。我希望该金额为$ 13,000(两张发票)。
我从搜索中得到的想法是,我需要在此处进行子选择,但无法对其进行分类。我很抱歉,因为原始SQL不是我的麻烦所在-正常的Rails Active Record调用可以满足我99%的需求。
因此,总而言之,我需要所有相关发票的总和,而不仅仅是第一张。
答案 0 :(得分:1)
我敢肯定,有一个更好的解决方案,但是这个应该可以工作:
WITH cte AS (
SELECT
e.id,
e.category,
COALESCE(parent_id, e.id) AS parent_id,
ei.amount
FROM
expenditures e
JOIN
expenditures_items ei ON e.id = ei.expenditure_id
),
cte2 AS (
SELECT
id,
SUM(amount) FILTER (WHERE category = 'purchase_order') AS expentiture_total,
SUM(amount) FILTER (WHERE category = 'invoice') AS invoice_total
FROM (
SELECT
parent_id AS id,
category,
SUM(amount) AS amount
FROM cte
GROUP BY (parent_id, category)
) s
GROUP BY id
)
SELECT
*,
(invoice_total/expentiture_total - 1) * 100 AS percent
FROM
cte2
第一个CTE将两个表连接在一起。如果记录没有记录,COALESCE()
函数会将ID镜像为parent_id(如果category = 'purchase_order'
)。可以用来对此ID和类别执行一个单独的GROUP
。
这是在第二个CTE(最内部的子查询)中完成的。 [Btw:我选择CTE变体是因为我发现它更具可读性。在这种情况下,您当然可以将所有步骤作为子查询来进行。]该组总结了每个({parent_
)id
的不同类别。
外部子查询正在执行数据透视。借助GROUP BY
和FILTER
子句,它将每个类别的不同记录转换成您期望的结果(请看小提琴中的此步骤以了解它)。不用担心这里的SUM()
函数。由于GROUP BY
,一个聚合函数是必需的,但是它没有任何作用,因为分组已经完成。
最后一步是从数据透视表中计算百分比值。