简体   繁体   English

mysql数据透视表到postgres数据透视表

[英]mysql pivot to a postgres pivot table

I was using mysql just fine until I recently switched one of my rails apps to heroku and had to change over. 在最近将我的一个Rails应用程序切换到heroku并不得不进行转换之前,我一直使用mysql很好。 Almost everything works as expected except I have one query which does something totally funky. 几乎所有的东西都按预期工作,除了我有一个查询,它完全是时髦的。

This is the postgres, but under mysql it is mostly identical except for the EXTRACT DOW and some group by additions, but that isn't the problem, the problem is it used to SUM the days of the week listed, now it sums the entire table... and also the AVG is off since it also gets the table avg and not the days listed. 这是postgres,但是在mysql下,除了EXTRACT DOW和一些按添加项分组以外,其他几乎是相同的,但这不是问题,问题在于它用于对所列的星期几求和,现在将其总和表格...而AVG也已关闭,因为它还会获取表格平均值,而不是列出的日期。

Is there a way to get a sum of the listed days without having to do another select, something i'm missing?... I would like to avoid doing SELECT ( SELECT ... ) as SUBQUERY just to get a sum of the columns. 有没有一种方法可以获取列出的天数的总和而不必进行其他选择,而我却错过了某些事情?...我想避免将SELECT(SELECT ...)作为子查询来获取总和列。

Thanks 谢谢

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

You didn't say what the schema is, so I pretended all of the data was in one table, omitting the join. 您没有说架构是什么,所以我假装所有数据都在一个表中,而忽略了联接。 It should be no trouble to replace "stuff" with your join. 用您的联接替换“ stuff”应该没有问题。

I created a simple table to stand in for your join: 我创建了一个简单的表来代表您的加入:

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)

Added some data to it: 向其中添加了一些数据:

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)

And here's a query for the last two full days, plus today, grouped by date, with count, sum and avg price. 这是最近两个整天以及今天的查询,按日期分组,并带有计数,总和和平均价格。

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)

All you need to do is limit the results to the past 3 days. 您需要做的就是将结果限制在过去3天之内。 This will prevent the avg/sum from being performed on the entire table...Add this to your existing query (taken from Wayne, who got a +1 for the effort) 这将阻止在整个表上执行平均/总和...将其添加到现有查询中(取自韦恩,他获得了+1的努力)

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

Sorry, I should have included what the output looks like: 抱歉,我应该包含输出内容:

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

And the input: 和输入:

+----+-------+-------+------------+---------+---------------------------+---------------------------+
| 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 |
+----+-------+-------+------------+---------+---------------------------+---------------------------+

Below works and does what I want it to, except for the avgs but it's really messy... as I couldn't figure out how to sum in any other way without getting sums of all nights instead of just 2-5... ie $120 vs $20,512. 下面的方法可以做到我想要的,除了avgs之外,但确实很混乱...因为我无法弄清楚如何以其他任何方式求和而不要得到整夜而不是2-5的总和...即$ 120 vs $ 20,512。 The solution below was to do the same MAX as above for pivoted days... day1 day2... and just doing the same to add them together. 下面的解决方案是对数据透视天... day1 day2 ...执行与上述相同的MAX,然后执行相同的操作将它们加在一起。

The join is not important, its only to pull the name of the room. 联接并不重要,它只是拉出房间的名称。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM