missing years - replace with empty row - postgresql

I am tying to retrieve some data and it is as below:
id
year
value
1
2015
200
1
2016
3000
1
2018
500
2
2010
455
2
2015
678
2
2020
100
as you can see some years are missing - I would like to add the rows with missing years, null for column value and I want to do it per specific ids - any ideas?

You can combine GENERATE_SERIES() with a left join do expand the missing years. For example:
select x.id, x.y, t.value
from (select id, generate_series(min(year), max(year)) as y from t group by id) x
left join t on t.id = x.id and t.year = x.y
Result:
id y value
--- ----- -----
1 2015 200
1 2016 3000
1 2017 null
1 2018 500
2 2010 455
2 2011 null
2 2012 null
2 2013 null
2 2014 null
2 2015 678
2 2016 null
2 2017 null
2 2018 null
2 2019 null
2 2020 100

Related

In Redshift SQL query for reducing years

i have data with fields as shown below
id
grade
grade_id
year
Diff
101
5
7
2022
9
105
k
2
2021
2
106
4
6
2020
5
110
pk
1
2022
1
i want to insert records for same id until we reaches grade = pk , Like shown below for every record in the table .
id
grade
grade_id
year
Diff
101
5
7
2022
9
101
4
6
2021
8
101
3
5
2020
7
101
2
4
2019
6
101
1
3
2018
5
101
k
2
2017
4
101
pk
1
2016
3
need help in sql code
create table amish.cte_test
(id int,
grade int,
year int,
diff int)
insert into amish.cte_test
values (101,5,2022,9)
with recursive temp1( id, grade, year, diff) as
(select id, grade , year , diff from amish.cte_test
union all
select id, grade-1, year-1,diff-1 from temp1
where grade-1 > -2)
select * from temp1

How to dynamic calculate value using formulas in postgresql

I'm in new this field. How do I manage the dynamic calculation with formulas and what steps to achieve the below output?.
I have tables.
Table 1 - Info_question table is for details about questions name and id.
q_id
questions_name
1
A
2
B
3
C
4
D
Table 2 - data_question is for data values.
id
q_id
period
data_value
1
1
2022
1000
2
1
2021
2000
3
2
2022
3000
4
3
2022
4000
5
4
2022
5000
I need to calculate A+B+C and that output will insert into data_question table and new question will create in the info_question table.(formulas will change for new question like A/B*100 or A+C and question id will be new generate)
For (A+B+C) Output should be shows like below tables.
data_question table
id
q_id
period
data_value
1
1
2022
1000
2
1
2021
2000
3
2
2022
3000
4
3
2022
4000
5
4
2022
5000
6
5
2022
8000
7
5
2021
2000
and info_question
q_id
questions_name
1
A
2
B
3
C
4
D
5
E

PostgresSQL: Fill values for null rows based on rows for which we do have values

I have the following table:
country year rank
1 Austria 2019 1
2 Austria 2018 NA
3 Austria 2017 NA
4 Austria 2016 NA
5 Spain 2019 2
6 Spain 2018 NA
7 Spain 2017 NA
8 Spain 2016 NA
9 Belgium 2019 3
10 Belgium 2018 NA
11 Belgium 2017 NA
12 Belgium 2016 NA
I want to fill in the NA values for 2018, 2017 and 2016 for each country with the value for 2019 (which we have).
I want the output table to look like this:
country year rank
1 Austria 2019 1
2 Austria 2018 1
3 Austria 2017 1
4 Austria 2016 1
5 Spain 2019 2
6 Spain 2018 2
7 Spain 2017 2
8 Spain 2016 2
9 Belgium 2019 3
10 Belgium 2018 3
11 Belgium 2017 3
12 Belgium 2016 3
I do not know where to get started with this question. I typically work with R but am now working on a platform which uses postgresSQL. I could do this in R but thought it would be worthwhile to figure out how it is done with postgres.
Any help with this would be greatly appreciated. Thank you.
Using an update to join to find the non NULL rank value for each country:
UPDATE yourTable AS t1
SET "rank" = t2.max_rank
FROM
(
SELECT country, MAX("rank") AS max_rank
FROM yourTable
GROUP BY country
) t2
WHERE t2.country = t1.country;
-- AND year IN (2016, 2017, 2018)
Add the commented out portion of the WHERE clause if you really only want to target certain years (your example seems to imply that you want to backfill all missing data).
If you just want to view your data in the format of the output, then use MAX as an analytic function:
SELECT country, year, MAX("rank") OVER (PARTITION BY country) AS "rank"
FROM yourTable
ORDER BY country, year DESC;
If you just want the output then
try this,
with cte as (
select distinct on (country) * from test
order by country, year desc
)
select
t1.id,t1.country,t1.year,t2.rank
from test t1 left join cte t2 on t1.country=t2.country
If you want to update your table then try this:
with cte as (
select distinct on (country) * from test
order by country, year desc
)
update test set rank=cte.rank from cte
where test.country=cte.country
DEMO

Find max value in a group in FileMaker

How to select only max values in a group in the following set
id productid price year
---------------------------
1 11 0,10 2015
2 11 0,12 2016
3 11 0,11 2017
4 22 0,08 2016
5 33 0,02 2016
6 33 0,01 2017
Expected result for each productid and max year would be
id productid price year
---------------------------
3 11 0,11 2017
4 22 0,08 2016
6 33 0,01 2017
This works for me.
ExecuteSQL (
"SELECT t.id, t.productid, t.price, t.\"year\"
FROM test t
WHERE \"year\" =
(SELECT MAX(\"year\") FROM test tt WHERE t.productid = tt.productid)"
; " " ; "")
Adapted from this answer:
https://stackoverflow.com/a/21310671/832407
A simple SQL query will give you a last year for every product record
ExecuteSQL (
"SELECT productid, MAX ( \"year\")
FROM myTable
GROUP By productid";
"";"" )
To get to the price for that year is going to be trickier, as FileMaker SQL does not fully support subqueries or temp tables.

Partitioned by Year

I have a year table like this. Every year has 12 values (Fixed)
declare #t table (FiscalYear int,[Month] varchar(25))
insert into #t values
(2011,'Jan'),(2011,'Feb'),(2011,'Mar'),(2011,'Apr'),
(2011,'May'),(2011,'Jun'),(2011,'Jul'),(2011,'Aug'),
(2011,'Sep'),(2011,'Oct'),(2011,'Nov'),(2011,'Dec'),
(2012,'Jan'),(2012,'Feb'),(2012,'Mar'),(2012,'Apr'),
(2012,'May'),(2012,'Jun'),(2012,'Jul'),(2012,'Aug'),
(2012,'Sep'),(2012,'Oct'),(2012,'Nov'),(2012,'Dec'),
(2013,'Jan'),(2013,'Feb'),(2013,'Mar'),(2013,'Apr'),
(2013,'May'),(2013,'Jun'),(2013,'Jul'),(2013,'Aug'),
(2013,'Sep'),(2013,'Oct'),(2013,'Nov'),(2013,'Dec')
I want to output as
FYear Month Qt Qtp
2011 Jan 1 1
2011 Feb 1 2
2011 Mar 1 3
2011 Apr 2 1
2011 May 2 2
2011 Jun 2 3
2011 Jul 3 1
2011 Aug 3 2
2011 Sep 3 3
2011 Oct 4 1
2011 Nov 4 2
2011 Dec 4 3
2012 Jan 1 1
2012 Feb 1 2
2012 Mar 1 3
2012 Apr 2 1
2012 May 2 2
2012 Jun 2 3
2012 Jul 3 1
2012 Aug 3 2
2012 Sep 3 3
2012 Oct 4 1
2012 Nov 4 2
2012 Dec 4 3
2013 Jan 1 1
2013 Feb 1 2
2013 Mar 1 3
2013 Apr 2 1
2013 May 2 2
2013 Jun 2 3
2013 Jul 3 1
2013 Aug 3 2
2013 Sep 3 3
2013 Oct 4 1
2013 Nov 4 2
2013 Dec 4 3
How can i do that in SQLServer2008R2. I have tried using DenseRank, RowNuber, Partitioned but all in vain.
Tru using Ntile:
--select * from #t
SELECT * ,
ROW_NUMBER() OVER ( PARTITION BY FYear, Qt ORDER BY FYear ) Qtp
from
(SELECT FYear,[Month],
NTILE(4) OVER ( PARTITION BY FYear ORDER BY FYear ) AS Qt
FROM #t) PERIOD
ORDER BY FYear ,Qt ,ROW_NUMBER() OVER ( PARTITION BY FYear, Qt ORDER BY FYear)
I propose dynamically populating a table with date values from Dec 2013 going down to the year that you like (you can alter the #COUNT_Y Variable to add more years).
SQL has some interesting datetime functions like DATEPART which can tell you which quarter a month is in etc.
** Answer changed due to question change **
DECLARE #DATES TABLE
(
xDATE DATETIME
)
DECLARE #STARTDATE DATETIME = '12-31-2013'
DECLARE #COUNT_X INT = 0
DECLARE #COUNT_X_MAX INT = 11
DECLARE #COUNT_Y INT = 0
DECLARE #COUNT_Y_MAX INT = 2
WHILE (#COUNT_Y <= #COUNT_Y_MAX)
BEGIN
SET #COUNT_X = 0
WHILE (#COUNT_X <= #COUNT_X_MAX)
BEGIN
INSERT INTO #DATES
SELECT DATEADD(MONTH, -#COUNT_X, DATEADD(YEAR,-#COUNT_Y, #STARTDATE))
SET #COUNT_X = #COUNT_X + 1
END
SET #COUNT_Y = #COUNT_Y + 1
END
SELECT * FROM
(SELECT
DATEPART(YEAR, D.xDATE) AS [YEAR],
DATEPART(MONTH, D.xDATE) AS [MONTH],
DATENAME(MONTH, D.xDATE) AS [MONTH_NAME],
DATEPART(QUARTER, D.xDATE) AS [QUARTER],
DATEPART(MONTH, D.xDATE) - (3 * (DATEPART(QUARTER, D.xDATE) - 1)) AS [QTP]
FROM #DATES D) t
ORDER BY T.YEAR, T.MONTH