如何在Postgresql中水平组合同一表上的两个select查询?
各位。我是Postgresql的初学者。最近我遇到了一个问题。 我有一张名为“sales”的桌子如何在Postgresql中水平组合同一表上的两个select查询?,postgresql,join,pivot,subquery,inner-join,Postgresql,Join,Pivot,Subquery,Inner Join,各位。我是Postgresql的初学者。最近我遇到了一个问题。 我有一张名为“sales”的桌子 create table sales ( cust varchar(20), prod varchar(20), day integer, month integer, year integer, state char(2), quant intege
create table sales
(
cust varchar(20),
prod varchar(20),
day integer,
month integer,
year integer,
state char(2),
quant integer
);
insert into sales values ('Bloom', 'Pepsi', 2, 12, 2001, 'NY', 4232);
insert into sales values ('Knuth', 'Bread', 23, 5, 2005, 'PA', 4167);
insert into sales values ('Emily', 'Pepsi', 22, 1, 2006, 'CT', 4404);
insert into sales values ('Emily', 'Fruits', 11, 1, 2000, 'NJ', 4369);
insert into sales values ('Helen', 'Milk', 7, 11, 2006, 'CT', 210);
insert into sales values ('Emily', 'Soap', 2, 4, 2002, 'CT', 2549);
insert into sales values ('Bloom', 'Eggs', 30, 11, 2000, 'NJ', 559);
。。。。
总共有498行。
以下是此表的概述:
现在,我想计算每个产品的最大和最小销售量,以及相应的客户(购买产品的客户)、日期(即最大和最小销售量的日期)和销售交易发生的状态。
以及相应产品的平均销售数量
组合的应该是这样的:
它应该有10行,因为总共有10个不同的产品
我试过:
select prod,
max(quant),
cust as MAX_CUST
from sales
group by prod;
但它返回了一个错误,并说cust应该在组中。但我只想按产品类型分类
此外,我如何将max\u q及其客户、日期、状态与min\u q及其客户、日期、状态以及AVG\u q按其产品名称进行横向组合?
我感到很困惑 对一列应用两个聚合函数(最小值、最大值)并选择相应的行并不是那么简单。如果你只需要一个聚合函数,你可以用密集秩(窗口函数)做下面的例子
您不能使用
分组依据
在此处选择最小/最大值,因为您希望获得量程的最小/最大值的完整行,这是分组依据
无法直接实现的 您可以使用分析函数ROW_NUMBER通过增加/减少子查询中每个产品的销售额来对记录进行排名,然后进行条件聚合:
SELECT
prod product,
MAX(CASE WHEN rn2 = 1 THEN quant END) max_quant,
MAX(CASE WHEN rn2 = 1 THEN cust END) max_cust,
MAX(CASE WHEN rn2 = 1 THEN TO_DATE(year || '-' || month || '-' || day, 'YYYY-MM-DD') END) max_date,
MAX(CASE WHEN rn2 = 1 THEN state END) max_state,
MAX(CASE WHEN rn1 = 1 THEN quant END) min_quant,
MAX(CASE WHEN rn1 = 1 THEN cust END) min_cust,
MAX(CASE WHEN rn1 = 1 THEN TO_DATE(year || '-' || month || '-' || day, 'YYYY-MM-DD') END) min_date,
MAX(CASE WHEN rn1 = 1 THEN state END) min_state,
avg_quant
FROM (
SELECT
s.*,
ROW_NUMBER() OVER(PARTITION BY prod ORDER BY quant) rn1,
ROW_NUMBER() OVER(PARTITION BY prod ORDER BY quant DESC) rn2,
AVG(quant) OVER(PARTITION BY prod) avg_quant
FROM sales s
) x
WHERE rn1 = 1 OR rn2 = 1
GROUP BY prod, avg_quant
对于未来的问题:最好将样本数据表示为。有关如何创建美观的表格的一些提示,请参阅。首先非常感谢您的帮助。我运行了
SELECT prod,quant cust densite_rank()(按生产订单按数量描述划分)作为销售中的c_rank,其中c_rank<2
但是,它仍然说语法错误在稠密的_rank()附近……所选字段之间缺少一个逗号。更新后的查询将选择prod、quant、cust、densite_rank()(按生产订单划分,按quant DESC)作为销售中的c_rank,其中c_rank<2代码>非常感谢您的帮助!!!我从“s.*”中删除了“s”,并在平均值(quant)中添加了一个round(),它最终输出了我想要的结果。只是你能告诉我为什么“s.*”不起作用,这是什么类型的语法???@WikizVito:s
只是sales
表的别名。我刚刚更新了查询(没有声明别名),现在应该可以正常工作了。好的,谢谢!为什么我不能通过使用round()获得平均值的整数呢?@WikizVito:round()
将按预期工作,就像这样:round(平均值(quant)超过(按产品分区))平均值。
。是的,你说得对!我把右括号的位置弄错了。非常感谢。
with max_quant as (
SELECT prod, quant cust,
dense_rank() OVER (PARTITION BY prod ORDER BY quant DESC) AS c_rank
FROM sales WHERE c_rank < 2
),
min_quant as (
SELECT prod, quant cust,
dense_rank() OVER (PARTITION BY prod ORDER BY quant DESC) AS c_rank
FROM sales WHERE c_rank < 2
),
avg_quant as (
select prod, avg(quant) as avg_quant from sales group by prod
)
select mx.prod, mx.quant, mx.cust, mn.quant, mn.cust, ag.avg_quant
from max_quant mx
join min_quant mn on mn.prod = mx.prod
join avg_quant ag on ag.prod = mx.prod;
SELECT
prod product,
MAX(CASE WHEN rn2 = 1 THEN quant END) max_quant,
MAX(CASE WHEN rn2 = 1 THEN cust END) max_cust,
MAX(CASE WHEN rn2 = 1 THEN TO_DATE(year || '-' || month || '-' || day, 'YYYY-MM-DD') END) max_date,
MAX(CASE WHEN rn2 = 1 THEN state END) max_state,
MAX(CASE WHEN rn1 = 1 THEN quant END) min_quant,
MAX(CASE WHEN rn1 = 1 THEN cust END) min_cust,
MAX(CASE WHEN rn1 = 1 THEN TO_DATE(year || '-' || month || '-' || day, 'YYYY-MM-DD') END) min_date,
MAX(CASE WHEN rn1 = 1 THEN state END) min_state,
avg_quant
FROM (
SELECT
s.*,
ROW_NUMBER() OVER(PARTITION BY prod ORDER BY quant) rn1,
ROW_NUMBER() OVER(PARTITION BY prod ORDER BY quant DESC) rn2,
AVG(quant) OVER(PARTITION BY prod) avg_quant
FROM sales s
) x
WHERE rn1 = 1 OR rn2 = 1
GROUP BY prod, avg_quant