【问题标题】:mysql pivot to a postgres pivot tablemysql 到 postgres 数据透视表
【发布时间】:2010-01-11 19:38:39
【问题描述】:

在我最近将我的一个 Rails 应用程序切换到 Heroku 之前,我一直使用 mysql 并不得不进行更改。几乎一切都按预期工作,除了我有一个查询完全时髦。

这是 postgres,但在 mysql 下,除了 EXTRACT DOW 和一些 group by 添加之外,它几乎是相同的,但这不是问题,问题是它习惯于 对列出的星期几求和,现在它对整个表格求和...而且 AVG 也关闭了,因为它还获取表格 avg 而不是列出的日期。

有没有办法获得列出的天数的总和而不必再做一次选择,我错过了什么?...我想避免做 SELECT (SELECT ...) as SUBQUERY 只是为了得到一个列的总和。

谢谢

SELECT rooms.name, rooms.id,
MAX(CASE WHEN (EXTRACT(DOW FROM availables.bookdate) - EXTRACT(DOW FROM DATE '2010-01-20')) = -3 THEN (availables.price*1) ELSE 0 END) AS day1,
MAX(CASE WHEN (EXTRACT(DOW FROM availables.bookdate) - EXTRACT(DOW FROM DATE '2010-01-20')) = -2 THEN (availables.price*1) ELSE 0 END) AS day2,
MAX(CASE WHEN (EXTRACT(DOW FROM availables.bookdate) - EXTRACT(DOW FROM DATE '2010-01-20')) = -1 THEN (availables.price*1) ELSE 0 END) AS day3,
(AVG(availables.price)*1) AS avg,
(SUM(availables.price)*1) * 2 AS sum, 
MAX((SIGN(spots)-1) + 2) AS beds
 FROM availables
 INNER JOIN rooms
 ON availables.room_id=rooms.id
 WHERE availables.room_id = '1818' AND availables.price > 0
 GROUP BY rooms.id, rooms.name

【问题讨论】:

  • 你不能只添加一个 where 子句来过滤过去 3 天的结果吗?
  • spots 是可用位置的数量...还剩 2 张床位等。
  • 你能解释一下吗?:MAX((SIGN(spots)-1) + 2) AS 床
  • only one problem with that is that I don't have data for every day, some days may have no data for weeks. Not likely weeks, but possible. ;-(:::: 所以如果我读到这个,你的查询实际上想要从某个时间段中提取前 3 天。您能帮我们定义一下这段时间吗?
  • 好吧,特定时间只是最新价格。唯一的问题是一周中的几天,周五和周六的价格往往高于工作日的价格。这就是为什么价格是一周中的几天。如果它只是对这些 MAX 进行平均和求和,我会喜欢它。

标签: mysql ruby-on-rails postgresql sum pivot


【解决方案1】:

你没有说架构是什么,所以我假装所有数据都在一个表中,省略了连接。用你的加入替换“东西”应该没有问题。

我创建了一个简单的表来代替您的加入:

wayne=# \d stuff
                            Table "pg_temp_1.stuff"
  Column  |     Type      |                     Modifiers
----------+---------------+----------------------------------------------------
 id       | integer       | not null default nextval('stuff_id_seq'::regclass)
 room_id  | integer       | not null
 bookdate | date          | not null
 price    | numeric(10,2) | not null
Indexes:
    "stuff_pkey" PRIMARY KEY, btree (id)

添加了一些数据:

wayne=# select * from stuff;
 id | room_id |  bookdate  | price
----+---------+------------+-------
  1 |       1 | 2010-01-11 | 60.00
  2 |       1 | 2010-01-10 | 60.00
  3 |       2 | 2010-01-10 | 55.00
  4 |       2 | 2010-01-09 | 55.00
  5 |       3 | 2010-01-09 | 70.00
  6 |       3 | 2010-01-08 | 70.00
(6 rows)

这是过去两天加上今天的查询,按日期分组,包括计数、总和和平均价格。

wayne=# select bookdate, count(*), sum(price), avg(price) from stuff \
where bookdate >= date_trunc('day', now()) - interval '2 days' \
group by bookdate order by bookdate;
  bookdate  | count |  sum   |         avg
------------+-------+--------+---------------------
 2010-01-09 |     2 | 125.00 | 62.5000000000000000
 2010-01-10 |     2 | 115.00 | 57.5000000000000000
 2010-01-11 |     1 |  60.00 | 60.0000000000000000
(3 rows)

【讨论】:

    【解决方案2】:

    您只需将结果限制在过去 3 天。这将阻止对整个表执行平均/总和...将此添加到您现有的查询中(取自韦恩,他的努力得到了 +1)

    AND availables.bookdate >= date_trunc('day', now()) - interval '2 days'
    

    【讨论】:

    • 只有一个问题是我没有每天的数据,有些日子可能几周都没有数据。不太可能几周,但可能。 ;-(
    • LIMIT 什么都不做,因为它必须在 group by 之后......除非有另一种方式我错过了......
    【解决方案3】:

    抱歉,我应该包括输出的样子:

    +------+--------+------------+-------+-------+-------+------+---------------------+
    | id   | sum    | name       | day1  | day2  | day3  | beds | avg                 |
    +------+--------+------------+-------+-------+-------+------+---------------------+
    | 1819 | 131.52 | 8 Bed Dorm | 21.92 | 21.92 | 21.92 | 2    | 21.8980952380952381 |
    +------+--------+------------+-------+-------+-------+------+---------------------+
    

    然后输入:

    +----+-------+-------+------------+---------+---------------------------+---------------------------+
    | id | price | spots | bookdate   | room_id | created_at                | updated_at                |
    +----+-------+-------+------------+---------+---------------------------+---------------------------+
    | 1  | 27.72 | 1     | 2009-09-14 | 1       | 2009-09-11 15:32:22 +0200 | 2009-09-11 15:32:22 +0200 |
    +----+-------+-------+------------+---------+---------------------------+---------------------------+
    

    下面的作品和我想要的,除了平均,但它真的很混乱......因为我无法弄清楚如何以任何其他方式求和而不得到所有夜晚的总和,而不是仅仅 2-5 ... 即 120 美元对 20,512 美元。下面的解决方案是对旋转天执行与上述相同的 MAX... day1 day2... 并且只需执行相同操作即可将它们加在一起。

    加入并不重要,它只是拉房间的名字。

    SELECT rooms.name, rooms.id,
    MAX(CASE WHEN (EXTRACT(DOW FROM availables.bookdate) - EXTRACT(DOW FROM DATE '2010-01-20')) = -3 THEN (availables.price*1) ELSE 0 END) AS day1,
    MAX(CASE WHEN (EXTRACT(DOW FROM availables.bookdate) - EXTRACT(DOW FROM DATE '2010-01-20')) = -2 THEN (availables.price*1) ELSE 0 END) AS day2,
    MAX(CASE WHEN (EXTRACT(DOW FROM availables.bookdate) - EXTRACT(DOW FROM DATE '2010-01-20')) = -1 THEN (availables.price*1) ELSE 0 END) AS day3,
    (MAX(CASE WHEN (EXTRACT(DOW FROM availables.bookdate) - EXTRACT(DOW FROM DATE '2010-01-20')) = -3 THEN (availables.price*1) ELSE 0 END) + 
    MAX(CASE WHEN (EXTRACT(DOW FROM availables.bookdate) - EXTRACT(DOW FROM DATE '2010-01-20')) = -2 THEN (availables.price*1) ELSE 0 END) + 
    MAX(CASE WHEN (EXTRACT(DOW FROM availables.bookdate) - EXTRACT(DOW FROM DATE '2010-01-20')) = -1 THEN (availables.price*1) ELSE 0 END)) *1 * 2 AS sum, 
    (AVG(availables.price)*1) AS avg, 
    MAX((SIGN(spots)-1) + 2) AS beds
     FROM availables
     INNER JOIN rooms
     ON availables.room_id=rooms.id
     WHERE availables.room_id = '1819' AND availables.price > 0
     GROUP BY rooms.id, rooms.name
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-07
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 2020-08-28
      • 2023-03-08
      • 1970-01-01
      相关资源
      最近更新 更多