问题描述
假设我有一个数据库,其中有一个比萨店的数据。我通过两个表customer
和orders
来跟踪客户及其订单。 orders
具有customer
的FK,因此我可以轻松查看哪些订单属于哪个客户。
我可以像这样计算所有客户的订单:
SELECT
c.id,COUNT(o.id) AS order_counts
FROM
customers AS c,JOIN orders ON c.id = o.customer_id
GROUP BY
c.id
这给了我这样的东西:
results = [
{
“customer_number”: 1,“order_counts”: 5
},{
“customer_number”: 2,“order_counts”: 10
}]
但是,如果我想“分解” order_counts结果以显示所有披萨类型,然后计算这些类型怎么办?我将添加一个名为pizzas
的新表,该表具有一个name
列,然后使结果看起来像这样:
results = [
{
“customer_number”: 1,“counts”: {
“Hawaiian”: 2,“Meat lovers”: 2,"Four Cheese": 1
}
},“counts”: {
“Hawaiian”: 5,“Meat lovers”: 5,"Four Cheese": 0
}
}]
我需要利用哪些sql主体/范例来实现这一目标?我怀疑我需要子查询和/或嵌套的GROUP BY语句。
奖金问题:这在Django ORM中是可能的,还是很快达到ORM局限性的东西?
解决方法
结果可能包含多个客户ID,但数字是披萨特有的。
SELECT
c.id,COUNT(o.id) AS order_counts,p.name
FROM
customers AS c,JOIN orders o ON c.id = o.customer_id
JOIN pizzas p ON p.id = o.pizzas_id
GROUP BY
c.id,p.name
,
如果您确实想要这种嵌套输出,那么最好直接从数据库中生成JSON:
select
c.id customer_id,sum(no_pizzas) no_orders,jsonb_object_agg(p.name,o.cnt_pizza) counts
from customers AS c,inner join (
select customer_id,pizza_id,count(*) cnt_pizza
from orders o
group by customer_id,pizza_id
) o on c.id = o.customer_id
inner join pizza p on p.id = o.pizza_id
group by c.id
这将产生列counts
作为json对象,并以披萨名称为键,而披萨计数为值。另外,您仍然可以在no_orders
列中获得订单总数。
如果您想吸引没有订单的客户,请使用left join
s:
select
c.id customer_id,coalesce(sum(no_pizzas),0) no_orders,left join (
select customer_id,pizza_id
) o on c.id = o.customer_id
left join pizza p on p.id = o.pizza_id
group by c.id