我如何使用下面描述的原点 table 和预期 table 分析 PostgreSQL 上的数据?
How can I analyse data on PostgreSQL using the origin table and expectant table I have described below?
我的数据是这样的:
Item
Year
Price
Hat
2020
15
Hat
2021
17
Hat
2022
19
Pen
2020
3
Pen
2021
2
Pen
2022
3.3
我想使用 PostgreSQL 实现一个简单的数据分析任务,将提供以下结果:
Item
Year
Price
Previous Year
Previous price
higher_than_previous_year
Hat
2020
15
Hat
2021
17
2020
15
yes
Hat
2022
19
2021
17
yes
Pen
2020
3
Pen
2021
2
2020
3
no
Pen
2022
3.3
2021
2
yes
上一年: 获取小于年份列中指定的当前年份的最近年份。
上一价格: 获取与上一年对应的商品价格。
higher_than_previous_year:将价格栏与上一个价格栏进行比较,当价格高于前一价格时计算是,当前一价格高于当年价格时计算否。
如果有任何 PostgreSQL 专家能对此进行破解,我将不胜感激。谢谢!
您可以使用简单的 JOINS
和 UNION
来实现此目的(多种方法之一):
查询:
SELECT
a.item,
a.year,
a.price,
NULL AS prev_year,
NULL AS prev_price,
NULL AS higher_than_previous_year
FROM
(
Select *, ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Year) as rn
from t
) as a
WHERE rn=1
UNION
SELECT
a.item,
a.year,
a.price,
b.year as prev_year,
b.price as prev_price,
CASE
WHEN a.price > b.price THEN 'yes'
ELSE 'No'
END AS higher_than_previous_year
FROM
(
Select *, ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Year) as rn
from t
) as a
LEFT JOIN
(
Select *, ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Year) as rn
from t
) as b
ON a.item=b.item and a.rn=b.rn+1
WHERE a.rn>1
解释:
- 首先创建一个
ROW_NUM
列来查找前几行 - 在所有使用 FROM
和 JOIN
的地方使用相同的 table
- 以上
UNION
: 获取带有 1 的行,因为它们很容易继续
- 低于
UNION
: 自加入 table 以获取其上一个值
中的fiddle
如果您有访问权限,我建议创建 intermediate tables
以便查询看起来更简单。请参阅此 fiddle(创建了中间 tables,因此查询易于理解和调试)
只需使用 lag window function, which allows you to look back the previous row(s). Since this requires several look back operation, you define and use a WINDOW definition in the query. (see demo)
select item, year, price
, lag(year) over w previous_year
, lag(price) over w previous_price
, case when price > lag(price) over w then 'Yes'
when lag(price) over w is null then null::text
else 'No'
end higher_than_previous_year
from origin
window w as (partition by item order by year);
我之前在对@arun 的解决方案的评论之一中指出,有一个名为 'category' 的额外列。我发现这个查询效果最好。
SELECT *,
CASE WHEN price > previous_price THEN 'yes'
WHEN price <= previous_price THEN 'no'
ELSE null
END AS is_current_year_price_higher
FROM
(
SELECT *,
LAG(year,1) OVER (PARTITION BY item, category ORDER BY item, year) AS previous_year,
LAG(price,1) OVER (PARTITION BY item, category ORDER BY item, year) AS previous_price
FROM table_name
) AS main
我的数据是这样的:
Item | Year | Price |
---|---|---|
Hat | 2020 | 15 |
Hat | 2021 | 17 |
Hat | 2022 | 19 |
Pen | 2020 | 3 |
Pen | 2021 | 2 |
Pen | 2022 | 3.3 |
我想使用 PostgreSQL 实现一个简单的数据分析任务,将提供以下结果:
Item | Year | Price | Previous Year | Previous price | higher_than_previous_year |
---|---|---|---|---|---|
Hat | 2020 | 15 | |||
Hat | 2021 | 17 | 2020 | 15 | yes |
Hat | 2022 | 19 | 2021 | 17 | yes |
Pen | 2020 | 3 | |||
Pen | 2021 | 2 | 2020 | 3 | no |
Pen | 2022 | 3.3 | 2021 | 2 | yes |
上一年: 获取小于年份列中指定的当前年份的最近年份。 上一价格: 获取与上一年对应的商品价格。 higher_than_previous_year:将价格栏与上一个价格栏进行比较,当价格高于前一价格时计算是,当前一价格高于当年价格时计算否。
如果有任何 PostgreSQL 专家能对此进行破解,我将不胜感激。谢谢!
您可以使用简单的 JOINS
和 UNION
来实现此目的(多种方法之一):
查询:
SELECT
a.item,
a.year,
a.price,
NULL AS prev_year,
NULL AS prev_price,
NULL AS higher_than_previous_year
FROM
(
Select *, ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Year) as rn
from t
) as a
WHERE rn=1
UNION
SELECT
a.item,
a.year,
a.price,
b.year as prev_year,
b.price as prev_price,
CASE
WHEN a.price > b.price THEN 'yes'
ELSE 'No'
END AS higher_than_previous_year
FROM
(
Select *, ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Year) as rn
from t
) as a
LEFT JOIN
(
Select *, ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Year) as rn
from t
) as b
ON a.item=b.item and a.rn=b.rn+1
WHERE a.rn>1
解释:
- 首先创建一个
ROW_NUM
列来查找前几行 - 在所有使用FROM
和JOIN
的地方使用相同的 table - 以上
UNION
: 获取带有 1 的行,因为它们很容易继续 - 低于
UNION
: 自加入 table 以获取其上一个值
如果您有访问权限,我建议创建 intermediate tables
以便查询看起来更简单。请参阅此 fiddle(创建了中间 tables,因此查询易于理解和调试)
只需使用 lag window function, which allows you to look back the previous row(s). Since this requires several look back operation, you define and use a WINDOW definition in the query. (see demo)
select item, year, price
, lag(year) over w previous_year
, lag(price) over w previous_price
, case when price > lag(price) over w then 'Yes'
when lag(price) over w is null then null::text
else 'No'
end higher_than_previous_year
from origin
window w as (partition by item order by year);
我之前在对@arun 的解决方案的评论之一中指出,有一个名为 'category' 的额外列。我发现这个查询效果最好。
SELECT *,
CASE WHEN price > previous_price THEN 'yes'
WHEN price <= previous_price THEN 'no'
ELSE null
END AS is_current_year_price_higher
FROM
(
SELECT *,
LAG(year,1) OVER (PARTITION BY item, category ORDER BY item, year) AS previous_year,
LAG(price,1) OVER (PARTITION BY item, category ORDER BY item, year) AS previous_price
FROM table_name
) AS main