Calculate Average of Price per Items per Month in a Few Years Postgresql - postgresql

I have this table inside my postgresql database,
item_code | date | price
==============================
aaaaaa.1 |2019/12/08 | 3.04
bbbbbb.b |2019/12/08 | 19.48
261893.c |2019/12/08 | 7.15
aaaaaa.1 |2019/12/17 | 4.15
bbbbbb.2 |2019/12/17 | 20
xxxxxx.5 |2019/03/12 | 3
xxxxxx.5 |2019/03/18 | 4.5
how can i calculate the average per item, per month over the year. so i get the result something like:
item_code | month | price
==============================
aaaaaa.1 | 2019/12 | 3.59
bbbbbb.2 | 2019/12 | 19.74
261893.c | 2019/12 | 7.15
xxxxxx.5 | 2019/03 | 3.75
I have tried to look and apply many alternatives but i am still not get the point, would really appreciate your help because i am new to postgresql.

I don't see how the question relates to a moving average. It seems you just want group by:
select item_code, date_trunc('month', date) as date_month, avg(price) as price
from mytable
group by item_code, date_month
This gives date_month as a date, truncated to the first day of the month - which I find more useful that the format you suggested. But it you do want that:
to_char(date, 'YYYY/MM') as date_month

Related

How to calculate current month / six months ago and result as a percent change in Postgresql?

create table your_table(type text,compdate date,amount numeric);
insert into your_table values
('A','2022-01-01',50),
('A','2022-02-01',76),
('A','2022-03-01',300),
('A','2022-04-01',234),
('A','2022-05-01',14),
('A','2022-06-01',9),
('B','2022-01-01',201),
('B','2022-02-01',33),
('B','2022-03-01',90),
('B','2022-04-01',41),
('B','2022-05-01',11),
('B','2022-06-01',5),
('C','2022-01-01',573),
('C','2022-02-01',77),
('C','2022-03-01',109),
('C','2022-04-01',137),
('C','2022-05-01',405),
('C','2022-06-01',621);
I am trying to calculate to show the percentage change in $ from 6 months prior to today's date for each type. In example:
Type A decreased -82% over six months.
Type B decreased -97.5%
Type C increased +8.4%.
How do I write this in postgresql mixed in with other statements?
It looks like comparing against 5, not 6 months prior, and 2022-06-01 isn't today's date.
Join the table with itself based on the matching type and desired time difference. Demo
select
b.type,
b.compdate,
a.compdate "6 months earlier",
b.amount "amount 6 months back",
round(-(100-b.amount/a.amount*100),2) "change"
from your_table a
inner join your_table b
on a.type=b.type
and a.compdate = b.compdate - '5 months'::interval;
-- type | compdate | 6 months earlier | amount 6 months back | change
--------+------------+------------------+----------------------+--------
-- A | 2022-06-01 | 2022-01-01 | 9 | -82.00
-- B | 2022-06-01 | 2022-01-01 | 5 | -97.51
-- C | 2022-06-01 | 2022-01-01 | 621 | 8.38

Stored procedure (or better way) to add a new row to existing table every day at 22:00

I will be very grateful for your advice regarding the following issue.
Given:
PostgreSQL database
Initial (basic) query
select day, Value_1, Value_2, Value_3
from table
where day=current_date
which returns a row with following columns
Day | Value_1(int) | Value_2(int) | Value 3 (int)
2019-11-14 | 10 | 10 | 14
It is needed to create a view with this starting information and add a new row every day based on the outcome of initial query executed at 22:00.
The expected outcome tomorrow at 22:01 will be
Day | Value_1 | Value_2 | Value_3
2019-11-14 | 10 | 10 | 14
2019-11-15 | N | M | P
Many thanks in advance for your time and support.

Cognos Calculate Variance Crosstab (Dimensional)

This is very similar to Cognos Calculate Variance Crosstab (Relational), but my data source is dimensional.
I have a simple crosstab such as this:
| 04-13-2013 | 04-13-2014
---------------------------------------
Sold | 75 | 50
Purchased | 10 | 15
Repaired | 33 | 44
Filter: The user selects 1 date and then we include that date plus 1 year ago.
Dimension: The date is the day level in a YQMD Hierarchy.
Measures: We are showing various measures from a Measure Dimension.
Sold
Purchased
Repaired
Here is what is looks like in report studio:
| <#Day#> | <#Day#>
---------------------------------------
<#Sold#> | <#1234#> | <#1234#>
<#Purchased#> | <#1234#> | <#1234#>
<#Repaired#> | <#1234#> | <#1234#>
I want to be able to calculate the variance as a percentage between the two time periods for each measure like this.
| 04-13-2013 | 04-13-2014 | Var. %
-----------------------------------------------
Sold | 75 | 50 | -33%
Purchased | 10 | 15 | 50%
Repaired | 33 | 44 | 33%
I added a Query Expression to the right of the <#Day#> as shown below, but I cannot get the variance calculation to work.
| <#Day#> | <#Variance#>
---------------------------------------
<#Sold#> | <#1234#> | <#1234#>
<#Purchased#> | <#1234#> | <#1234#>
<#Repaired#> | <#1234#> | <#1234#>
These are the expressions I've tried and the results that I get:
An expression that is hard coded works, but only for that 1 measure:
total(case when [date] = 2014-04-13 then [Sold] end)
/
total(case when [date] = 2013-04-13 then [Sold] end)
-1
I thought CurrentMember and PrevMember might work, but it produces blank cells:
CurrentMember( [YQMD Hierarchy] )
/
prevMember(CurrentMember([YQMD Hierarchy]))
-1
I think it is because prevMember produces blank.
prevMember(CurrentMember([YQMD Hierarchy]))
Using only CurrentMember gives a total of both columns:
CurrentMember([YQMD Hierarchy])
What expression can I use to take advantage of my dimensional model and add a column with % variance?
These are the pages I used for research:
Variance reporting in Report Studio on Cognos 8.4?
Calculations that span dimensions - PDF
IBM Cognos 10 Report Studio: Creating Consumer-Friendly Reports
I hope there is a better way to do this. I finally found a resource that describes one approach to this problem. Using the tail and head functions, we can get to the first and last periods, and thereby calculate the % variance.
item(tail(members([Day])),0)
/
item(head(members([Day])),0)
-1
This idea came from IBM Cognos BI – Using Dimensional Functions to Determine Current Period.
Example 2 – Find Current Period by Filtering on Measure Data
If the OLAP or DMR data source has been populated with time periods into the future (e.g. end of year or future years), then the calculation of current period is more complicated. However, it can still be determined by finding the latest period that has data for a given measure.
item(tail(filter(members([sales_and_marketing].[Time].[Time].[Month]),
tuple([Revenue], currentMember([sales_and_marketing].[Time].[Time]))
is not null), 1), 0)

DB2, get all rows with 1/100 of a column

I have these rows in my product table:
product_name | product_code | percentage.
prod1#00X | 1 | 50
prod2#00X | 2 | 20
prod3#00X | 3 | 30
I wanna select all the elements of my table but I wanna show 1/100 of the percentage
The result should be:
prod1#00X | 1 | 0.50
prod2#00X | 2 | 0.20
prod3#00X | 3 | 0.30
How can I do?
I wanna find another solution not this:
SELECT product_name, product_code, (percentage/100) as percentage FROM product
Note: I have several columns in my table, not only product_name | product_code | percentage.
Try this way:
SELECT (percentage/100) as percentage,*
FROM product
OR
Using another alias:
SELECT *,(percentage/100) as NewPercentage
FROM product
you can use select statement as
SELECT *
, (percentage/100) as newpercentage
FROM product
where (your condition )

Joining sequential records in TSQL

I've got a database of messages which contain various pieces of information that come in. One such piece is a state change messages so my table looks like the following.
+-----------+--------------+---------+
| MessageId | RecievedUTC | State |
+-----------+--------------+---------+
| 1 | 1/1/2010 5pm | Off |
+-----------+--------------+---------+
| 2 | 1/2/2010 8am | Idle |
+-----------+--------------+---------+
| 3 | 1/2/2010 9am | Working |
+-----------+--------------+---------+
I'd like get a list of records which state how long I was in each state something like for a report and a maybe a pretty bar chart of how time was spent.
+---------+---------------+--------------+
| State | StartUTC | StopUTC |
+---------+---------------+--------------+
| Off | 1/1/2010 5pm | 1/2/2010 8am |
+---------+---------------+--------------+
| Idle | 1/1/2010 8am | 1/2/2010 9am |
+---------+---------------+--------------+
etc. In my mind its no harder than a join of the table with itself, offset by 1 record ordered by the RecievedUTC.
The best TSQL I could come up with is something to the effect of
SELECT m1.State, m1.RecievedUTC as StartUTC, MIN(m2.RecievedUTC) as StopUTC
FROM MessageStates as m1
INNER JOIN MessageStates as m2 ON MessageStates ON m2.RecievedUTC > m1.RecievedUTC
GROUP BY m1.MessageId, m1.State, m1.RecievedUTC
Or as a sub query to get StopUTC but both perform horribly with only 30-40k records taking almost 5 minutes to do this join.
If I wrote this in C# I would keep the track of the previous RecievedUTC and state so when I saw the next record I could combine the next RecievedUTC with it and in linear time have the data as I wanted it.
Try this:
WITH MsgStates AS
(
SELECT a.*, ROW_NUMBER() OVER(ORDER BY RecievedUTC ) RN
FROM MessageStates a
)
SELECT a.State, a.RecievedUTC StartUTC, b.RecievedUTC StartUTC
FROM MsgStates a, MsgStates b
WHERE a.rn = b.rn+1