按类型对计数进行分组时使用哪个 SQL 范例?
Which SQL paradigm to use when grouping counts by type?
假设我有一个数据库,其中包含来自一家披萨店的数据。我通过两个 table 跟踪客户和他们的订单: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
的新 table,它有一个 name
列,然后让我的结果如下所示:
results = [
{
“customer_number”: 1,
“counts”: {
“Hawaiian”: 2,
“Meat Lovers”: 2,
"Four Cheese": 1
}
},
{
“customer_number”: 2,
“counts”: {
“Hawaiian”: 5,
“Meat Lovers”: 5,
"Four Cheese": 0
}
}]
我需要利用哪个 SQL principals/paradigms 来实现这一目标?我怀疑我需要一个子查询 and/or 一个嵌套的 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,
jsonb_object_agg(p.name, o.cnt_pizza) counts
from customers AS c,
left 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
left join pizza p on p.id = o.pizza_id
group by c.id
假设我有一个数据库,其中包含来自一家披萨店的数据。我通过两个 table 跟踪客户和他们的订单: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
的新 table,它有一个 name
列,然后让我的结果如下所示:
results = [
{
“customer_number”: 1,
“counts”: {
“Hawaiian”: 2,
“Meat Lovers”: 2,
"Four Cheese": 1
}
},
{
“customer_number”: 2,
“counts”: {
“Hawaiian”: 5,
“Meat Lovers”: 5,
"Four Cheese": 0
}
}]
我需要利用哪个 SQL principals/paradigms 来实现这一目标?我怀疑我需要一个子查询 and/or 一个嵌套的 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,
jsonb_object_agg(p.name, o.cnt_pizza) counts
from customers AS c,
left 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
left join pizza p on p.id = o.pizza_id
group by c.id