【问题标题】:SQL query : transform rows to columnsSQL查询:将行转换为列
【发布时间】:2019-06-20 10:19:36
【问题描述】:

这是我的桌子的一个例子。

我需要做一个查询,显示那些在两个月(11 或 12)中的一个或两个月中的一个费用为 0 的 ID。

因此,从示例中,我需要显示 ID 1、3、4 而不是 2,如下面的屏幕截图所示。

我尝试了以下查询:

SELECT 
    t1.id, t1.month, t1.fee, t2.id, t2.month, t2.fee
FROM
    table t1, table t2
WHERE t1.id = t2.id
  AND t1.month = '11'
  AND t2.month = '12'
  AND (t1.fee = 0 OR t2.fee = 0);

但是通过这个查询,我只看到 ID 1,3 而不是 ID 4。我猜这是因为 t1.id = t2.id 但不知道该怎么做。

【问题讨论】:

  • stackoverflow.com/questions/20618323/… 可能会有所帮助。
  • 今日提示:始终使用现代、明确的JOIN 语法。更容易编写(没有错误),更容易阅读和维护,如果需要更容易转换为外连接!

标签: sql postgresql pivot crosstab


【解决方案1】:

您可以使用条件聚合。在 Postgres 中,这可以利用 filter 语法:

SELECT t.id,
       11 as month,
       MAX(t.fee) FILTER (WHERE t.month = 11) as fee_11, 
       12 as month,
       MAX(t.fee) FILTER (WHERE t.month = 12) as fee_12
FROM t
GROUP BY t.id
HAVING MAX(t.fee) FILTER (WHERE t.month = 11) = 0 OR
       MAX(t.fee) FILTER (WHERE t.month = 12) = 0;

注意:两个月份的列是多余的。

【讨论】:

  • 嗨,我刚刚尝试了您的查询,但它不理解最后一行的 fee_11 / fee_12。你知道为什么吗?
  • @ayay 。 . .我只是忘记了 Postgres 不支持 HAVING 子句中的列别名。
【解决方案2】:

你需要条件聚合

  select id,month,max(case when month=11 then fee end) fee11,
     max(case when month=12 then fee end) as fee12
    from (
    select * from table t1
    where t1.id in ( select id from table where fee=0)
    ) a group by id,month

【讨论】:

  • 您好,您的查询成功了,但它并没有给出我想要的。比如 ID 3 和 1 出现了 2 次...
【解决方案3】:

Sql ansi 兼容查询

    SELECT id, 
        MAX(CASE WHEN MONTH = 11 THEN MONTH ELSE NULL END) AS month11, 
        MAX(CASE WHEN MONTH = 11 THEN fee ELSE NULL END) AS fee11, 
        MAX(CASE WHEN MONTH = 12 THEN MONTH ELSE NULL END) AS month12, 
        MAX(CASE WHEN MONTH = 12 THEN fee ELSE NULL END ) AS fee12
    FROM t
    GROUP BY id
    HAVING ( MAX(CASE WHEN MONTH = 11 THEN fee ELSE NULL END) = 0 OR MAX(CASE WHEN MONTH = 12 THEN fee ELSE NULL END ) = 0 )
    ORDER BY id

【讨论】:

  • 但是,我想知道是否有办法使用“外连接”而不是“max(case...)”,你有什么想法吗?
  • 这将是一个完整的外部联接,您可能有一个 12 月份的 id,而对应的 id 没有任何 11 月份的行。此外,这意味着扫描表 t 两次。 sql SELECT COALESCE( t11.id, t12.id ) AS id, t11.month AS month11, t11.fee AS fee11, t12.month AS month12, t12.fee AS fee12 FROM (SELECT * FROM t WHERE MONTH = 11 ) AS t11 FULL OUTER JOIN ( SELECT * FROM t WHERE MONTH = 12 ) AS t12 ON t11.id = t12.id WHERE ( t11.fee = 0 OR t12.fee = 0 )
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多