I have a table as below. The table holds the price of a product for each day in a year. I would like to get price change for each day by year.
Product Year 1Jan 2Jan .................... 31Dec
A 2018 10 20 .................... 120
A 2019 130 150 .................... 200
B 2018 15 23 .................... 90
B 2019 113 130 .................... 220
I would like to compare columns sequentially with year overlaps and get output as below.
• For the year 2018, by negating the value 2 Jan from 1 Jan (2 Jan-1 Jan), we get the new value of 2 Jan.
• For the year 2018, by negating the value 3Jan from 2 Jan (3 Jan-2 Jan), we get the new value of 3 Jan.
• For the year 2018, by negating the value 31Dec from 30 Dec (31 Dec-30 Dec), we get the new value of 31 Dec
• Now, For the year 2019, by negating the value 31 Dec(2018 year) from 1 Jan (2019 year), we get the new value of 1 Jan, 2019
So, in a nutshell, the value of a column is the difference of its value with previous day value.
Product Year 1Jan 2Jan .................... 31Dec
A 2018 10 10 .................... 15 (just assume value of 30Dec column is 105)
A 2019 10 20 .................... 10 (just assume value of 30Dec column is 190)
B 2018 15 8 .................... 8 (just assume value of 30Dec column is 82)
B 2019 23 17 .................... 10 (just assume value of 30Dec column is 210)
Let me know, if things are not clear.
Though logically there is nothing in this query, but still you have to work hard to write it -
SELECT Product
,Year
,1Jan
,2Jan - 1Jan 2Jan
,3Jan - 2Jan 3Jan
.
.
.
,31Dec - 30Dec 31Dec
FROM YOUR_TAB
ORDER BY Product
,Year;
first of all I think the design of the table could be better but thats a topic for some other time. Right now below code should work -
SELECT Product, Year,
1Jan AS '1st Jan',
2Jan-1Jan AS '2nd Jan',
3Jan-2Jan AS '3rd Jan',
4Jan-3Jan AS '4th Jan',
.
.
.
.
.
31Dec-30Dec AS '31st Dec',
FROM [table name];
Related
I have a table of names with two different dates. I want to know the count of names that are occurring between the two dates and the overlap percentage.
This is the output format that is desired. I am not looking for dates in between. I am looking for records that are in July 05 and also in August 10. Overlap percentage for each id would be - count of records in July 5 and also August 10/count of records on July 5.(Actual table has dates in date datatype).
Overlap % will always be less than or equal to 100 since count of records existing on July 5 as well as August 10 will always be <=count of records on July 5.
id
Count on July 05
Count of IDs from July 05 included in August 10
% overlap
ABC
BCD
CDE
DEF
EFG
Rough version of the input table
id
type
Group
date
ABC
Mobile
1
July 5
BCD
Mobile
1
July 5
ABC
Desktop
1
August 10
CDE
Mobile
2
July 5
BCD
Mobile
2
August 10
As I understood from your comments, the overlap will be the minimum count value of the two dates, i.e. for ABC if we have 6 in July and 2 in August the overlap will be 2, and if we have 3 in July and 5 in August the overlap will be 3.
If that is the case then you may use the following query tested on MS SQL Server 2019:
SELECT t.id, t.[Count on July 05],
CASE
WHEN t.[Count on July 05]<= t.[Count of August 10] THEN t.[Count on July 05]
WHEN t.[Count on July 05]> t.[Count of August 10] THEN t.[Count of August 10]
END AS [Count of IDs from July 05 included in August 10],
CASE
WHEN t.[Count on July 05]<= t.[Count of August 10] THEN CAST(t.[Count on July 05]*1.00/t.[Count on July 05] * 100 AS DECIMAL(18, 2))
WHEN t.[Count on July 05]> t.[Count of August 10] THEN CAST(t.[Count of August 10]*1.00/t.[Count on July 05] * 100 AS DECIMAL(18, 2))
END AS [% overlap]
FROM(
SELECT id,
COUNT(CASE WHEN [tdate] IN ('July 5') THEN 1 END) as [Count on July 05],
COUNT(CASE WHEN [tdate] IN ('August 10') THEN 1 END) as [Count of August 10]
FROM [Tbl]
GROUP BY id) t
I hope that is what you are looking for.
Could you help me out with an issue I have in Oracle?
Let's say I have a table that tells me about how many items were sold in each month, and looks like so:
Item
January
February
March
April
Computer
3
5
2
9
TV
10
12
16
14
Camera
22
25
20
27
What I need in the output is a table that would count the total number of items sold over the period, and would look like this:
Item
January
February
March
April
Total
Computer
3
5
2
9
19
TV
10
12
16
14
52
Camera
22
25
20
27
94
I am honestly not sure how to do that. Should I use grouping()?
Thank you in advance.
You don't need to use grouping at all just try to plus all columns as a new column Total.
SELECT T.*,
(January + February + March + April) Total
FROM T
I am trying to write a PostgreSQL query to return the first and last dates corresponding to indices. I have a table:
Datetime
Index
March 1 2021
0
March 2 2021
0
March 3 2021
0
March 4 2021
1
March 5 2021
1
March 6 2021
2
In this case, I would want to return:
I am wondering how I would write the PostgreSQL query for this.
I think this can be done with the following:
SELECT MIN("Datetime") AS Start
, MAX("Datetime") AS End
, "Index"
FROM <your_table>
GROUP BY "Index"
ORDER BY "Index"
;
I have table like below
customer
date
end date
1
jan 1 2021
jan 30 2021
1
jan 2 2021
jan 31 2021
1
jan 3 2021
feb 1 2021
1
jan 27 2021
feb 26 2021
1
feb 3 2021
mar 5 2021
2
jan 2 2021
jan 31 2021
2
jan 10 2021
feb 9 2021
2
feb 10 2021
mar 12 2021
Now, I wanted to update the value in the 'end date' column of a row based on the values in the previous row 'end date' and the current row 'date'.
Say if the date in current row < end date of the previous row, I wanted to update the end date of the current row = (end date of the previous row).
I Wanted to do this repeated for all the rows (grouped by customer).
I want the output as below. Just need it in the select statement instead of a updating/inserting in a table.
Note - in below as the second row(end date) is updated with the value in the first row (jan 30 2021), now the third row value (jan 3 2021) is evaluated against the updated value in the second row (which is jan 30 2021) but not with the second row value before update (jan 31 2021).
customer
date
end date
1
jan 1 2021
jan 30 2021
1
jan 2 2021
jan 30 2021 [updated because current date < previous end date]
1
jan 3 2021
jan 30 2021[updated because current date < previous end date]
1
jan 27 2021
jan 30 2021 [updated because current date < previous end date]
1
feb 3 2021
mar 5 2021
2
jan 2 2021
jan 31 2021
2
jan 10 2021
jan 31 2021[updated because current date < previous end date]
2
feb 10 2021
mar 12 2021
I think I should go this way. I use the datasource twice just to get the way its needed to perform the operation without updating or inserting into the table.
input table:
1|2021-01-01|2021-01-30
1|2021-01-02|2021-01-31
1|2021-01-03|2021-02-01
1|2021-01-27|2021-02-26
1|2021-02-03|2021-03-05
2|2021-01-02|2021-01-31
2|2021-01-10|2021-02-09
2|2021-02-10|2021-03-12
code:
with num_raw_data as (
SELECT row_number() over(partition by customer)as num, customer,date_init,date_end
FROM `project-id.data-set.table`
), analyzed_data as(
select r.num,
r.customer,
r.date_init,
r.date_end,
case when date_init<(select date_end from num_raw_data where num=r.num-1 and customer=r.customer and EXTRACT(month FROM r.date_init)=EXTRACT(month FROM date_init)) then 1 else 0 end validation
from num_raw_data r
)
select customer,
date_init,
case when validation !=0 then (select MIN(date_end) from analyzed_data where validation=0 and customer=ad.customer and date_init<ad.date_end) else date_end end as date_end
from analyzed_data ad
order by customer,num
output:
1|2021-01-01|2021-01-30
1|2021-01-02|2021-01-30
1|2021-01-03|2021-01-30
1|2021-01-27|2021-01-30
1|2021-02-03|2021-03-05
2|2021-01-02|2021-01-31
2|2021-01-10|2021-01-31
2|2021-02-10|2021-03-12
Using column validation from analyzed_data to get to know where I should be looking for changes. I'm not sure if its fast (probably not) but it works for the scenario you bring in your question.
I have a table where I want to join to bring through an i.d, straight forward enough but I only want to bring through values that are 'live' (referenced by a 1 in the flag column below). On the latest year no values are live yet but I need these values brought through too. It might be easier to explain in an example.
Joining Table:
Company Year Product ID Flag
A 2019 X 100 0
A 2019 X 101 1
A 2019 Y 102 1
A 2019 Y 103 0
A 2019 Y 104 0
A 2020 X 105 1
A 2020 Y 106 0
A 2020 Y 107 1
A 2020 Y 108 0
A 2020 Z 109 1
A 2021 X 110 0
A 2021 Y 111 0
A 2021 Y 112 0
A 2021 Y 113 0
A 2021 Z 114 0
I need to bring through those values that have a 1 in the Flag column and then all values with a year of 2021 (when 2021 begins the values in the flag column for 2021 will swap to zeroes and 1s, with the need to only bring through the rows with a 1 in the flag column, again).
The need to bring through next years values will reoccur at the end of every year so the idea is to future proof this from further changes so adding a when year =2021 is not an option.
The original table has the company, year and product so when I join it will be on these three fields.
Any thoughts, let me know
Thanks
Is this what you want?
select t.*
from mytable t
where flag = 1 or year = extract(year from current_date)
This brings rows where flag has value 1 or where year is the current year.
Note that this uses standard date functions extract() and current_date - not all databases support this syntax, but they all have equivalent.