我正在多个记录上执行聚合函数,这些记录按公共ID分组。问题是,我还想导出一些其他字段,这些字段在分组记录中可能不同,但我想从其中一个记录中获取这些字段(第一个,根据查询的ORDER BY)。
起点示例:
SELECT
customer_id,
sum(order_total),
referral_code
FROM order
GROUP BY customer_id
ORDER BY date_created
我需要查询引用代码,但是在聚合函数之外执行它意味着我必须按该字段进行分组,这不是我想要的 - 在这个示例中我需要每个客户一行。我真的只关心第一个订单的推荐代码,我很乐意抛弃任何后来的推荐代码。
这是在PostgreSQL中,但也许来自其他数据库的语法可能足够相似。
拒绝解决方案:
答案 0 :(得分:1)
嗯,实际上非常简单。
首先,让我们编写一个将进行聚合的查询:
select customer_id, sum(order_total)
from order
group by customer_id
现在,让我们编写一个查询,返回给定customer_id的1st referral_code和date_created:
select distinct on (customer_id) customer_id, date_created, referral_code
from order
order by customer_id, date_created
现在,您只需加入2个选项:
select
x1.customer_id,
x1.sum,
x2.date_created,
x2.referral_code
from
(
select customer_id, sum(order_total)
from order
group by customer_id
) as x1
join
(
select distinct on (customer_id) customer_id, date_Created, referral_code
from order
order by customer_id, date_created
) as x2 using ( customer_id )
order by x2.date_created
我没有对它进行测试,因此可能存在拼写错误,但通常它应该可以正常工作。
答案 1 :(得分:0)
您需要window functions。 这是GROUP BY,但您仍然可以访问各行。 虽然只使用了Oracle等价物。
答案 2 :(得分:0)
也许是这样的:
SELECT
O1.customer_id,
O1.referral_code,
SQ.total
FROM
Orders O1
LEFT OUTER JOIN Orders O2 ON
O2.customer_id = O1.customer_id AND
O2.date_created < O1.date_created
INNER JOIN (
SELECT
customer_id,
SUM(order_total) AS total
FROM
Orders
GROUP BY
customer_id
) SQ ON SQ.customer_id = O1.customer_id
WHERE
O2.customer_id IS NULL
答案 3 :(得分:0)
如果date_created保证每个customer_id是唯一的,那么你可以这样做:
[简单表]
create table ordertable (customer_id int, order_total int, referral_code char, date_created datetime)
insert ordertable values (1,10, 'a', '2009-01-01')
insert ordertable values (2,15, 'b', '2009-01-02')
insert ordertable values (1,35, 'c', '2009-01-03')
[用更好的东西替换我的蹩脚表格名称:]]
SELECT
orderAgg.customer_id,
orderAgg.order_sum,
referral.referral_code as first_referral_code
FROM (
SELECT
customer_id,
sum(order_total) as order_sum
FROM ordertable
GROUP BY customer_id
) as orderAgg join (
SELECT
customer_id,
min(date_created) as first_date
FROM ordertable
GROUP BY customer_id
) as dateAgg on orderAgg.customer_id = dateAgg.customer_id
join ordertable as referral
on dateAgg.customer_id = referral.customer_id
and dateAgg.first_date = referral.date_created
答案 4 :(得分:0)
这样的事情能做到吗?
SELECT
customer_id,
sum(order_total),
(SELECT referral_code
FROM order o
WHERE o.customer_id = order.customer_id
ORDER BY date_created
LIMIT 1) AS customers_referral_code
FROM order
GROUP BY customer_id, customers_referral_code
ORDER BY date_created
这不需要你在两个地方维护WHERE子句并保持顺序重要性,但如果你需要像referral_code这样的“几十个字段”,它会变得非常毛茸茸。它也相当慢(至少在MySQL上)。
听起来像referral_code
,而且像它一样的数十个字段应该在客户表中,而不是订单表,因为它们在逻辑上与客户1:1关联,而不是订单。将它们移动到那里会使查询更简单。
这也可以解决问题:
SELECT
o.customer_id,
sum(o.order_total),
c.referral_code, c.x, c.y, c.z
FROM order o LEFT JOIN (
SELECT referral_code, x, y, z
FROM orders c
WHERE c.customer_id = o.customer_id
ORDER BY c.date_created
LIMIT 1
) AS c
GROUP BY o.customer_id, c.referral_code
ORDER BY o.date_created
答案 5 :(得分:0)
SELECT customer_id, order_sum,
(first_record).referral, (first_record).other_column
FROM (
SELECT customer_id,
SUM(order_total) AS order_sum,
(
SELECT oi
FROM order oi
WHERE oi.customer_id = o.customer_id
LIMIT 1
) AS first_record
FROM order o
GROUP BY
customer_id
) q