PostgreSQL crosstab()选项,带大小写和聚合

PostgreSQL crosstab()选项,带大小写和聚合,postgresql,join,case,aggregate,crosstab,Postgresql,Join,Case,Aggregate,Crosstab,我想创建一个透视表视图,显示每个旅行模式下的每月预订总数 表预订量: timestamp , bookings , provider_id 表提供者: provider_id , travel_mode 透视表函数和交叉表函数不用于执行此操作。所以我尝试使用JOIN和CASE。以下是查询: SELECT b.month, (CASE WHEN p.travel_mode=train then b.amount end)train, (CASE WHEN p.travel

我想创建一个透视表视图,显示每个
旅行模式下的每月预订总数

预订量

  timestamp
, bookings
, provider_id
提供者

  provider_id
, travel_mode
透视表函数和交叉表函数不用于执行此操作。所以我尝试使用JOIN和CASE。以下是查询:

  SELECT b.month, 
  (CASE WHEN p.travel_mode=train then b.amount end)train,
  (CASE WHEN p.travel_mode=bus then b.amount end)bus, 
  (CASE WHEN p.travel_mode=air then b.amount end)air
  FROM 
  (SELECT  to_char(date_,month) as month, travel_mode, sum(bookings) as amount
  from bookings as b
  join providers as p
  on b.provider_id=p.provider_id
  group by b.month, p.travel_mode)
  group by b.month;
然而,我得到一个错误,它说:

当我添加别名时,它会抛出一个错误,说:

最终结果应该是这样的

Month       Air             Bus            Train  
01          Amount(air)     Amount(Bus)    Amount(train)
我有一种感觉,这是一个小错误的地方,但我无法找出它在所有


另外,我不得不删除问题中的所有引文,因为它不允许我发布这篇文章。但是这些都在实际查询中处理。

您必须将子查询命名为错误消息所示的名称:

SELECT b.month, 
(CASE WHEN p.travel_mode=train then b.amount end)train,
(CASE WHEN p.travel_mode=bus then b.amount end)bus, 
(CASE WHEN p.travel_mode=air then b.amount end)air
FROM 
(SELECT  to_char(date_,month) as month, travel_mode, sum(bookings) as amount
from bookings as b
join providers as p
on b.provider_id=p.provider_id
group by b.month, p.travel_mode)
**as foo** group by b.month;

删除星号以使其工作。

多个问题。缺少的表别名只是其中之一。此查询应适用于以下情况:

SELECT month
     , sum(CASE WHEN travel_mode = 'train' THEN amount END) AS train
     , sum(CASE WHEN travel_mode = 'bus'   THEN amount END) AS bus
     , sum(CASE WHEN travel_mode = 'air'   THEN amount END) AS air
FROM  (
   SELECT to_char(timestamp, 'MM') AS month, travel_mode, sum(bookings) AS amount
   FROM   bookings  b
   JOIN   providers p USING (provider_id)
   GROUP  BY month, p.travel_mode
   ) sub
GROUP  BY month;
  • 字符串文字缺少单引号。(你似乎已经删除了那些你无法发布报价的错误印象。)

  • 子查询缺少表别名-如第一条错误消息所示

  • 在外部查询中,子查询中基础表的表名(或别名)不可见。只有子查询的表别名是。因为只有一个子查询,所以根本不需要表限定

  • month
    是一个输出列名(不在基础表中),因此表限定
    b.month
    也是错误的

  • 你似乎想要几个月的两位数数字。使用“
    to_char()”
    代替“month”

  • 外部查询中的聚合不像您之前那样工作-就像您的第二条错误消息所说的那样。必须将外部
    大小写
    表达式包装在聚合函数中。在这种情况下,您最好使用
    min()
    max()
    ,因为子查询后面的行永远不会超过一行

  • 还不清楚日期从哪里来?你是说时间戳?(这不是一个好的标识符)

但您不需要从子查询开始,可以简化为:

SELECT to_char(timestamp, 'MM') AS month
     , sum(CASE WHEN p.travel_mode = 'train' THEN b.bookings END) AS train
     , sum(CASE WHEN p.travel_mode = 'bus'   THEN b.bookings END) AS bus
     , sum(CASE WHEN p.travel_mode = 'air'   THEN b.bookings END) AS air
FROM   bookings  b
JOIN   providers p USING (provider_id)
GROUP  BY 1;
为获得最佳性能,您仍应使用
交叉表()
,不过:


您可以(也应该)发布所有报价。因此,这当然是允许的。您应该始终添加实际的表定义(
CREATE table
语句),显示数据类型和约束以及您的Postgres版本。第一次查询不起作用。这是它抛出的错误错误:列b.month不存在第9行:按b.month分组,p.travel\u mode^@justanothernewbie:现在已修复。请尝试最新版本。(
month
是一个输出列名,因此表限定错误。)
SELECT month
     , sum(CASE WHEN travel_mode = 'train' THEN amount END) AS train
     , sum(CASE WHEN travel_mode = 'bus'   THEN amount END) AS bus
     , sum(CASE WHEN travel_mode = 'air'   THEN amount END) AS air
FROM  (
   SELECT to_char(timestamp, 'MM') AS month, travel_mode, sum(bookings) AS amount
   FROM   bookings  b
   JOIN   providers p USING (provider_id)
   GROUP  BY month, p.travel_mode
   ) sub
GROUP  BY month;
SELECT to_char(timestamp, 'MM') AS month
     , sum(CASE WHEN p.travel_mode = 'train' THEN b.bookings END) AS train
     , sum(CASE WHEN p.travel_mode = 'bus'   THEN b.bookings END) AS bus
     , sum(CASE WHEN p.travel_mode = 'air'   THEN b.bookings END) AS air
FROM   bookings  b
JOIN   providers p USING (provider_id)
GROUP  BY 1;