PLsql or Oracle Sql - sql

Looking for a help on populating the data from table1 to table2.
I have table1 of below columns and data sample as below.
When days is 5 it needs to populate data on other table2 with 8 hours based on days (sat and sun needs to be 0 )
Table 1:
id year month days
101 2017 September 5
102 2017 September 4
103 2017 September 3
104 2017 September 2
Table 2 which needs to be populated as below:
Id Month 1 2(Sat) 3(Sunday) 4 5
101 September 8 0 0 8 8 8 8
102 September 8 0 0 8 8 8 0
103 September 8 0 0 8 8 0 0
104 September 8 0 0 8 0 0 0

You get the desired result with:
select
id,
month,
case when days >= 1 then 8 end as friday,
0 as saturday,
0 as sunday,
case when days >= 2 then 8 end as monday,
case when days >= 3 then 8 end as tuesday,
case when days >= 4 then 8 end as wednesday,
case when days >= 5 then 8 end as thursday
from table1
where year = 2017;
In order to fill table2 with this data, you can use an insert select:
insert into table2 (id, month, saturday, sunday, monday, tuesday, wednesday, thursday)
select
id,
...
from table1
where year = 2017;

Related

SQL query to Find highest value in table and sum the corresponding value

I would like to group Highest values in month column group by year and Sum the value column
value
Year
Month
4
2019
10
1
2019
11
5
2019
11
1
2019
11
1
2019
12
8
2019
12
1
2019
12
1
2020
1
10
2020
1
3
2021
1
2
2021
2
11
2021
2
1
2021
2
3
2021
2
2
2021
3
In above table I would like to extract highest value of month group by year
in year 2019 highest month is 12 so there are 3 rows and sum of value column will be 10
The output should be
value
Year
Month
10
2019
12
11
2020
1
2
2021
3
supposing that the table is called "example_table" you can use the following query:
select sum(example_table.value), example_table.year, example_table.month
from example_table
join (
select year, max(month) "month"
from example_table
group by year
) sub on example_table.year = sub.year and example_table.month = sub.month
group by example_table.year, example_table.month
order by example_table.year

R - get a vector that tells me if a value of another vector is the first appearence or not

I have a data frame of sales with three columns: the code of the customer, the month the customer bought that item, and the year.
A customer can buy something in september and then in december make another purchase, so appear two times. But I'm interested in knowing the absolutely new customoers by month and year.
So I have thought in make an iteration and some checks and use the %in% function and build a boolean vector that tells me if a customer is new or not and then count by month and year with SQL using this new vector.
But I'm wondering if there's a specific function or a better way to do that.
This is an example of the data I would like to have:
date cust month new_customer
1 14975 25 1 TRUE
2 14976 30 1 TRUE
3 14977 22 1 TRUE
4 14978 4 1 TRUE
5 14979 25 1 FALSE
6 14980 11 1 TRUE
7 14981 17 1 TRUE
8 14982 17 1 FALSE
9 14983 18 1 TRUE
10 14984 7 1 TRUE
11 14985 24 1 TRUE
12 14986 22 1 FALSE
So put it more simple: the data frame is sorted by date, and I'm interested in a vector (new_customer) that tells me if the customer purchased something for the first time or not. For example customer 25 bought something the first day, and then four days later bought something again, so is not a new customer. The same can be seen with customer 17 and 22.
I create dummy data my self with id, month of numeric format, and year
dat <-data.frame(
id = c(1,2,3,4,5,6,7,8,1,3,4,5,1,2,2),
month = c(1,6,7,8,2,3,4,8,11,1,10,9,1,12,2),
year = c(2019,2019,2019,2019,2019,2020,2020,2020,2020,2020,2021,2021,2021,2021,2021)
)
id month year
1 1 1 2019
2 2 6 2019
3 3 7 2019
4 4 8 2019
5 5 2 2019
6 6 3 2020
7 7 4 2020
8 8 8 2020
9 1 11 2020
10 3 1 2020
11 4 10 2021
12 5 9 2021
13 1 1 2021
14 2 12 2021
15 2 2 2021
Then, group by id and arrange by year and month (order is meaningful). Then use filter and row_number().
dat %>%
group_by(id) %>%
arrange(year, month) %>%
filter(row_number() == 1)
id month year
<dbl> <dbl> <dbl>
1 1 1 2019
2 5 2 2019
3 2 6 2019
4 3 7 2019
5 4 8 2019
6 6 3 2020
7 7 4 2020
8 8 8 2020
Sample Code
You can change in your code according to this logic:-
Create Table:-
CREATE TABLE PURCHASE(Posting_Date DATE,Customer_Id INT,Customer_Name VARCHAR(15));
Insert Data Into Table
Posting_Date Customer_Id Customer_Name
2018-01-01 C_01 Jack
2018-02-01 C_01 Jack
2018-03-01 C_01 Jack
2018-04-01 C_02 James
2019-04-01 C_01 Jack
2019-05-01 C_01 Jack
2019-05-01 C_03 Gill
2020-01-01 C_02 James
2020-01-01 C_04 Jones
Code
WITH Date_CTE (PostingDate,CustomerID,FirstYear)
AS
(
SELECT MIN(Posting_Date) as [Date],
Customer_Id,
YEAR(MIN(Posting_Date)) as [F_Purchase_Year]
FROM PURCHASE
GROUP BY Customer_Id
)
SELECT T.[ActualYear],(CASE WHEN T.[Customer Status] = 'new' THEN COUNT(T.[Customer Status]) END) AS [New Customer]
FROM (
SELECT DISTINCT YEAR(T2.Posting_Date) AS [ActualYear],
T2.Customer_Id,
(CASE WHEN T1.FirstYear = YEAR(T2.Posting_Date) THEN 'new' ELSE 'old' END) AS [Customer Status]
FROM Date_CTE AS T1
left outer join PURCHASE AS T2 ON T1.CustomerID = T2.Customer_Id
) AS T
GROUP BY T.[ActualYear],T.[Customer Status]
Final Result
ActualYear New Customer
2018 2
2019 1
2020 1
2019 NULL
2020 NULL

Custom SQL for quarter count starting from previous month

I need to create a custom quarter calculator to start always from previous month no matter month, year we are at and count back to get quarter. Previous year wuarters are to be numbered 5, 6 etc
So the goal is to move quarter grouping one month back.
Assume we run query on December 11th, result should be:
YEAR MNTH QTR QTR_ALT
2017 1 1 12
2017 2 1 12
2017 3 1 11
2017 4 2 11
2017 5 2 11
2017 6 2 10
2017 7 3 10
2017 8 3 10
2017 9 3 9
2017 10 4 9
2017 11 4 9
2017 12 4 8
2018 1 1 8
2018 2 1 8
2018 3 1 7
2018 4 2 7
2018 5 2 7
2018 6 2 6
2018 7 3 6
2018 8 3 6
2018 9 3 5
2018 10 4 5
2018 11 4 5
2018 12 4 1
2019 1 1 1
2019 2 1 1
2019 3 1 2
2019 4 2 2
2019 5 2 2
2019 6 2 3
2019 7 3 3
2019 8 3 3
2019 9 3 4
2019 10 4 4
2019 11 4 4
2019 12 4 THIS IS SKIPPED
Starting point is eliminating current_date so data end at previous month's last day
SELECT DISTINCT
YEAR,
MNTH,
QTR
FROM TABLE
WHERE DATA BETWEEN
(SELECT DATE_TRUNC(YEAR,ADD_MONTHS(CURRENT_DATE, -24))) AND
(SELECT DATE_TRUNC(MONTH,CURRENT_DATE)-1)
ORDER BY YEAR, MNTH, QTR
The following gets you all the dates you need, with the extra columns.
select to_char(add_months(a.dt, -b.y), 'YYYY') as year,
to_char(add_months(a.dt, -b.y), 'MM') as month,
ceil(to_number(to_char(add_months(a.dt, -b.y), 'MM')) / 3) as qtr,
ceil(b.y/3) as alt_qtr
from
(select trunc(sysdate, 'MONTH') as dt from dual) a,
(select rownum as y from dual connect by level <= 24) b;

How to Find Week number, Period and year from Date in Redshift? (Week Starting with Wednesday and ends up with Tuesday)

Need to find weekNumber like 1,2,3,4 but the week starts with Wednesday and ends with Tuesday from date column and after the 4th week, again the week restart by again as the 1st week and so on (no need to consider month).
Need to find the Period based on weekNumber only, 4 weeks as 1 Period and Periods end with 13 (period 1-13) will restart again 1st period.
(4 weeks = 1 period) (no need to consider month).
Now need to calculate the businessyear based on Period. 13 Periods as One businessyear. (13 periods = 1 year)
Calculation logic:
7 days * 4 weeks = 28 days = 1 period
13 periods = 1 businessyear
Example:
A year has 365 days normally
In my scenario, 4 weeks * 7 days = 28 days
28 days *13 periods = 364 days
The remaining days will come as the 5th week and period 14.
Datekey date Year semistor Quarter Month DayName DayNum Wnumber
20090101 01-01-2009 2009 1 1 January 1 Thursday 1 0
20090102 02-01-2009 2009 1 1 January 1 Friday 2 0
20090103 03-01-2009 2009 1 1 January 1 Saturday 3 0
20090104 04-01-2009 2009 1 1 January 1 Sunday 0
20090105 05-01-2009 2009 1 1 January 1 Monday 0
20090106 06-01-2009 2009 1 1 January 1 Tuesday 6 0
20090107 07-01-2009 2009 1 1 January 1 Wednesday 0 0
20090108 08-01-2009 2009 1 1 January 1 Thursday 1 1
20090109 09-01-2009 2009 1 1 January 1 Friday 2 1
20090110 10-01-2009 2009 1 1 January 1 Saturday 3 1
20090111 11-01-2009 2009 1 1 January 1 Sunday 4 1
20090112 12-01-2009 2009 1 1 January 1 Monday 5 1
20090113 13-01-2009 2009 1 1 January 1 Tuesday 6 1
20090114 14-01-2009 2009 1 1 January 1 Wednesday 0 1
No need to consider the month in my scenario, need to consider leap year also (2016, 2020).
The traditional way to do this type of thing is to create a calendar table in the database. Then, your queries can simply JOIN to the calendar table to extract the relevant value.
I find that the easiest way to create the calendar table is to use Excel. Simply write some formulas that provide the desired values and Copy Down for the next decade or so. Then, save the sheet as CSV and load it into the database.
This way, you can totally avoid complex calculations involving database functions and you can use whatever rules you wish.

SQL Query Return 0 on weeks in between

i have this query that works , but the result is not like i want
returns only year and weeks that has data , i want to return 0 to the result
for example this returns
year week totalstop
2017 50 7
2018 1 3
2018 3 5
but i want to return
year week totalstop
2017 50 7
2017 51 0
2017 52 0
2018 1 3
2018 2 0
2018 3 5
and so on
here is the current query
SELECT year(Stopdate)[year],datepart(week,date1) [week],sum(stop) totalstop
from Table1 where
building in (select item from dbo.fn_Split('A1,A2,A3,A4,A5',','))
and
date1 between '2017-12-12' and '2018-05-08'
and grp = 1
group by year(date1),datepart(week,date1)
order by year(date1),[week]
iam using ms sql-server 2016
need help to modify it to my needs as iam out of ideas atm.