我有两个问题。每个查询都会提取组织和客户之间的订单总数,以及订单的应收款总和。除日期范围外,查询相同。
SELECT org.organization_id, org.name, cust.name as customer,
count(*) as num_orders, round (sum(cast(o.total_charge as real))) as receivables
FROM
organization as org, orders as o, organization as cust, reconcile_order as ro
WHERE org.organization_id = o.shipper_org_id
and o.broker_org_id = cust.organization_id
and o.order_id = ro.order_id
and o.status = 'D'
and (ro.receive_payment_in_full = 0 or ro.receive_payment_in_full is NULL)
and (NOW()::DATE - o.delivery_confirmed_date::DATE) < 31
group by org.organization_id, org.name,
cust.name
order by org.name asc limit 20
SELECT org.organization_id, org.name, cust.name as customer,
count(*) as num_orders, round (sum(cast(o.total_charge as real))) as receivables
FROM
organization as org, orders as o, organization as cust, reconcile_order as ro
WHERE org.organization_id = o.shipper_org_id
and o.broker_org_id = cust.organization_id
and o.order_id = ro.order_id
and o.status = 'D'
and (ro.receive_payment_in_full = 0 or ro.receive_payment_in_full is NULL)
and (NOW()::DATE - o.delivery_confirmed_date::DATE) between 31 and 60
group by org.organization_id, org.name,
cust.name
order by org.name asc limit 20
但我需要进行一次查询,以便输出是一个表,其中第一个日期范围内的订单和应收款列,以及第二个日期范围的另一对列旁边的列。 (即num_orders&lt; 31,应收账款&lt; 31,num_orders 31-60,应收账款31-60)
答案 0 :(得分:1)
您可以将条件语句放在count()和sum()函数中。
因此,如果您调整了where子句以恢复所有订单(跨越两个日期范围),那么您可以在select子句中创建多个结果列,每个列都只根据您想要的日期范围进行计数和求和。
SELECT ...
count(CASE WHEN (NOW()::DATE - o.delivery_confirmed_date::DATE) < 31 THEN 1 ELSE NULL END) as num_orders_a,
round(sum(CASE WHEN (NOW()::DATE - o.delivery_confirmed_date::DATE) < 31 THEN cast(o.total_charge as real) ELSE NULL END)) as receivables_a,
count(CASE WHEN (NOW()::DATE - o.delivery_confirmed_date::DATE) BETWEEN 31 AND 60 THEN 1 ELSE NULL END) as num_orders_b,
round(sum(CASE WHEN (NOW()::DATE - o.delivery_confirmed_date::DATE) BETWEEN 31 AND 60 THEN cast(o.total_charge as real) ELSE NULL END)) as receivables_b
(same FROM, WHERE, GROUP BY, and ORDER BY sections)
答案 1 :(得分:1)
有很多方法可以让这只猫受到影响,并且在性能和代码可维护性之间存在着真正的潜在折衷。
这里的CTE将有助于代码可读性/透明度/可维护性。这有点像黑客的做法,但这是一个想法:
with order_data as (
SELECT
org.organization_id, org.name, cust.name as customer,
o.total_charge::real,
case
when current_date - o.delivery_confirmed_date::DATE < 31 then 1
when current_date - o.delivery_confirmed_date::date < 61 then 2
else 3
end as cat
FROM
organization as org,
orders as o,
organization as cust,
reconcile_order as ro
WHERE
org.organization_id = o.shipper_org_id
and o.broker_org_id = cust.organization_id
and o.order_id = ro.order_id
and o.status = 'D'
and (ro.receive_payment_in_full = 0 or ro.receive_payment_in_full is NULL)
)
select
organization_id, name, customer,
sum (case when cat = 1 then 1 else 0 end) as "Orders < 31",
round (sum (case when cat = 1 then total_charge else 0 end)) as "Rec < 31",
sum (case when cat = 2 then 1 else 0 end) as "Orders 31-60",
round (sum (case when cat = 2 then total_charge else 0 end)) as "Rec 31-60",
sum (case when cat = 3 then 1 else 0 end) as "Orders 61+",
round (sum (case when cat = 3 then total_charge else 0 end)) as "Rec 61+"
from order_data
group by
organization_id, name, name
order by name asc
我认为更常见的方法可能是通过&#34; days_delta&#34;来自CTE的列(作为current_date - o.delivery_confirmed_date::DATE
)并使您的求和函数看起来更像这样:
sum (case when days_delta between 31 and 60 then ... end) as "31-60"
而且......任何说你不需要CTE的人 - 他们都是对的。你没有。对我来说,它只是使代码更加愉快。
- 编辑 -
CTE中较不吸引人(且功能较少)的表亲,子查询:
select
organization_id, name, customer,
sum (case when cat = 1 then 1 else 0 end) as "Orders < 31",
round (sum (case when cat = 1 then total_charge else 0 end)) as "Rec < 31",
sum (case when cat = 2 then 1 else 0 end) as "Orders 31-60",
round (sum (case when cat = 2 then total_charge else 0 end)) as "Rec 31-60",
sum (case when cat = 3 then 1 else 0 end) as "Orders 61+",
round (sum (case when cat = 3 then total_charge else 0 end)) as "Rec 61+"
from (
SELECT
org.organization_id, org.name, cust.name as customer,
o.total_charge::real,
case
when current_date - o.delivery_confirmed_date::DATE < 31 then 1
when current_date - o.delivery_confirmed_date::date < 61 then 2
else 3
end as cat
FROM
organization as org,
orders as o,
organization as cust,
reconcile_order as ro
WHERE
org.organization_id = o.shipper_org_id
and o.broker_org_id = cust.organization_id
and o.order_id = ro.order_id
and o.status = 'D'
and (ro.receive_payment_in_full = 0 or ro.receive_payment_in_full is NULL)
) as order_data
group by
organization_id, name, name
order by name asc
答案 2 :(得分:0)
我不确定我理解你的确切问题,但是如何:
Select earlier_ones.organization_id,earlier_ones.organization_id, name, customer, earlier_ones.receivables, later_ones.receivables
FROM (
SELECT org.organization_id, org.name, cust.name as customer,
count(*) as num_orders, round (sum(cast(o.total_charge as real))) as receivables
FROM
organization as org, orders as o, organization as cust, reconcile_order as ro
WHERE org.organization_id = o.shipper_org_id
and o.broker_org_id = cust.organization_id
and o.order_id = ro.order_id
and o.status = 'D'
and (ro.receive_payment_in_full = 0 or ro.receive_payment_in_full is NULL)
and (NOW()::DATE - o.delivery_confirmed_date::DATE) < 31
group by org.organization_id, org.name,
cust.name
order by org.name asc limit 20
) earlier_ones
LEFT JOIN (
SELECT org.organization_id, org.name, cust.name as customer,
count(*) as num_orders, round (sum(cast(o.total_charge as real))) as receivables
FROM
organization as org, orders as o, organization as cust, reconcile_order as ro
WHERE org.organization_id = o.shipper_org_id
and o.broker_org_id = cust.organization_id
and o.order_id = ro.order_id
and o.status = 'D'
and (ro.receive_payment_in_full = 0 or ro.receive_payment_in_full is NULL)
and (NOW()::DATE - o.delivery_confirmed_date::DATE) between 31 and 60
group by org.organization_id, org.name,
cust.name
order by org.name asc limit 20
) later_ones ON earlier_ones.organization_id = later_ones.organization_id AND earlier_ones.name = later_ones.name;