【问题标题】:PostgreSQL and Crosstab(): ERROR: return and sql tuple descriptions are incompatiblePostgreSQL 和 Crosstab():错误:返回和 sql 元组描述不兼容
【发布时间】:2017-12-14 23:37:16
【问题描述】:

我正在运行以下基本SQL 查询:

SELECT
  a.project_name,
  CASE
    WHEN to_char(date_trunc('month', u.billing_period_start), 'MM-YYYY') = '07-2016' THEN 'July_2016'
    WHEN to_char(date_trunc('month', u.billing_period_start), 'MM-YYYY') = '08-2016' THEN 'August_2016'
    WHEN to_char(date_trunc('month', u.billing_period_start), 'MM-YYYY') = '09-2016' THEN 'September_2016'
  END AS billing_month,
  u.unique_visitor_count AS visitors
FROM table_1 u,
     (SELECT
       a.account_id AS project_id,
       a.project_name
     FROM table_2 a) a
WHERE u.project_id = a.project_id
AND date_trunc('month', u.billing_period_start) BETWEEN '2016-07-01' AND '2016-09-01'
ORDER BY 1, 2;

这个查询让我得到以下结果集: project_name | month_name | visitors -------------|----------------|--------- name_1 | August_2016 | 0 name_1 | July_2016 | 0 name_1 | September_2016 | 0 name_2 | August_2016 | 0 name_2 | July_2016 | 0 name_2 | September_2016 | 0 name_3 | August_2016 | 39 name_3 | July_2016 | 68 name_3 | September_2016 | 25 name_4 | August_2016 | 536914 name_4 | July_2016 | 16142 name_4 | September_2016 | 487117

我正在尝试使用以下crosstab() 查询:

选择 * 从交叉表 ('选择 a.project_name, to_char(date_trunc(''month'', u.billing_period_start),''MM-YYYY'')=''07-2016'' then ''July_2016'' 的情况 当 to_char(date_trunc(''month'', u.billing_period_start),''MM-YYYY'')=''08-2016'' 然后 ''August_2016'' 当 to_char(date_trunc(''month'', u.billing_period_start),''MM-YYYY'')=''09-2016'' then ''September_2016'' end as billing_month, u.unique_visitor_count 为访客 FROM table_1 u, (选择 a.account_id 作为 project_id,a.project_name 从表_2 a) a 其中 u.project_id = a.project_id 和 date_trunc(''month'', u.billing_period_start) 在 ''2016-07-01'' 和 ''2016-09-01'' 之间 按 1,2' 订购) AS (project_name TEXT, July_2016 INTEGER, August_2016 INTEGER, September_2016 INTEGER);

我想把上面的第一个结果集变成如下: project_name | July_2016 | August_2016 | September_2016 ------------|-----------|-------------|--------------- name_1 | 0 | 0 | 0 name_2 | 0 | 0 | 0 name_3 | 68 | 39 | 25 name_4 | 16142 | 536914 | 487117

但是我收到了错误:

错误:返回和 sql 元组描述不兼容

对于visitors,我永远不会有任何空或缺失的结果。我已经阅读了关于crosstab() 的第二个参数的先前帖子,但我认为我在这里不需要它。我尝试将crosstab() 中的INTEGER 列更改为NUMERIC,但仍然收到相同的错误。

我做错了什么?有人可以提供修改后的、有效的 crosstab() 查询来向我展示修复方法吗?

【问题讨论】:

    标签: sql postgresql crosstab


    【解决方案1】:

    我只会使用条件聚合:

    SELECT a.project_name,
           SUM(case when date_trunc('month', u.billing_period_start) = '2016-07-01'
                    then u.unique_visitor_count else 0
               end) as uv_201607,
           SUM(case when date_trunc('month', u.billing_period_start) = '2016-08-01' 
                    then u.unique_visitor_count else 0
               end) as uv_201608,
           SUM(case when date_trunc('month', u.billing_period_start) = '2016-09-01' 
                    then u.unique_visitor_count else 0
               end) as uv_201609
    FROM table_1 u JOIN
         table_2 a
         ON u.project_id = a.project_id
    WHERE  date_trunc('month', u.billing_period_start) BETWEEN '2016-07-01' AND '2016-09-01'
    GROUP BY a.project_name
    ORDER BY a.project_name;
    

    注意事项:

    • 无需在date_trunc() 上使用to_char()
    • 使用标准日期格式 -- YYYY-MM-DD。
    • FROM 子句中的子查询是不必要的。
    • 从不FROM 子句中使用逗号。始终使用正确、明确的 JOIN 语法。

    【讨论】:

    • 谢谢@gordon-linoff。同意我的日期格式有点草率;我曾在一些失败的尝试中追求过这一点,以使crosstab() 表现良好。我的FROM 子查询被故意混淆以保护一些专有信息——这对我的核心问题并不重要。我想坚持使用crosstab(),因为我有更多的日期列要合并——这三个是一个有代表性的例子。我从其他帖子中了解到,我可能不得不放弃这种方法,因为我有未知数量的未来日期列要构建,但现在我只是好奇如何让这个示例工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 2021-10-15
    • 1970-01-01
    • 2014-04-12
    • 2014-07-02
    • 1970-01-01
    • 2017-08-05
    相关资源
    最近更新 更多