POSTGRESQL Join on generated string property - sql

I got a table named work_schema_items which contains a couple of columns and the important one for this question is varchar column weekday. The contains the following values:
end_time start_time weekday
12:00 06:00 Monday
14:30 12:30 Monday
15:00 14:45 Monday
18:00 15:00 Monday
21:00 18:30 Monday
23:00 21:15 Monday
23:59 23:15 Monday
12:00 06:00 Tuesday
14:30 12:30 Tuesday
15:00 14:45 Tuesday
18:00 15:00 Tuesday
21:00 18:30 Tuesday
23:00 21:15 Tuesday
23:59 23:15 Tuesday
12:00 06:00 Wednesday
14:30 12:30 Wednesday
15:00 14:45 Wednesday
18:00 15:00 Wednesday
21:00 18:30 Wednesday
23:00 21:15 Wednesday
23:59 23:15 Wednesday
12:00 06:00 Thursday
14:30 12:30 Thursday
15:00 14:45 Thursday
18:00 15:00 Thursday
21:00 18:30 Thursday
23:00 21:15 Thursday
23:59 23:15 Thursday
12:00 06:00 Friday
14:30 12:30 Friday
15:00 14:45 Friday
18:00 15:00 Friday
21:00 18:30 Friday
23:00 21:15 Friday
23:59 23:15 Friday
When I run the following sql query:
select
t.date,
t.weekday,
work_schema_items.weekday
from (
select
dd::date as date,
to_char(dd, 'Day')::varchar as weekday
from
generate_series('2019-12-08'::timestamp, '2019-12-16'::timestamp, '1 day'::interval) dd
) as t
left join work_schema_items on t.weekday = work_schema_items.weekday
order by date
I get this result:
2019-12-08 Sunday NULL
2019-12-09 Monday NULL
2019-12-10 Tuesday NULL
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-11 Wednesday Wednesday
2019-12-12 Thursday NULL
2019-12-13 Friday NULL
2019-12-14 Saturday NULL
2019-12-15 Sunday NULL
2019-12-16 Monday NULL
What I'm expecting is to get the weekday value for every day just like I do with Wednesday. How come only Wednesday is properly joined? What am I doing wrong?
Thanks

I found the solution.
char is a fixed length datatype and Wednesday is the longest weekday string. It keeps its width even if I did convert it to varchar which resulted in that I tried to join "Monday " to "Monday".
A simple TRIM() solves the problem:
select
t.date,
t.weekday,
work_schema_items.weekday
from (
select
dd::date as date,
TRIM(to_char(dd, 'Day')::varchar) as weekday
from
generate_series('2019-12-08'::timestamp, '2019-12-16'::timestamp, '1 day'::interval) dd
) as t
left join work_schema_items on t.weekday = work_schema_items.weekday
order by date

Related

How to format datetime field in pandas

I have the following dataframe:
xl_file
Out[2]:
Day Description
Date
2011-01-26 Wednesday Republic Day
2011-03-02 Wednesday Mahashivratri
2011-04-12 Tuesday Ram Navmi
2011-04-14 Thursday Dr. Babasaheb Ambedkar Jayanti
2011-04-22 Friday Good Friday
... ...
2020-05-25 Monday Id-Ul-Fitr (Ramzan ID)
2020-10-02 Friday Mahatma Gandhi Jayanti
2020-11-16 Monday Diwali-Balipratipada
2020-11-30 Monday Gurunanak Jayanti
2020-12-25 Friday Christmas
[144 rows x 2 columns]
To convert Day column to datetime field i used the following code:
xl_file['Day'] = pd.to_datetime(xl_file['Day'], format = '%A')
Where i specified the format however i am getting this:
xl_file
Out[4]:
Day Description
Date
2011-01-26 1900-01-01 Republic Day
2011-03-02 1900-01-01 Mahashivratri
2011-04-12 1900-01-01 Ram Navmi
2011-04-14 1900-01-01 Dr. Babasaheb Ambedkar Jayanti
2011-04-22 1900-01-01 Good Friday
... ...
2020-05-25 1900-01-01 Id-Ul-Fitr (Ramzan ID)
2020-10-02 1900-01-01 Mahatma Gandhi Jayanti
2020-11-16 1900-01-01 Diwali-Balipratipada
2020-11-30 1900-01-01 Gurunanak Jayanti
2020-12-25 1900-01-01 Christmas
[144 rows x 2 columns]
How can i change formatting so the datetime field shows day name.
I tried this:
xl_file['Day'].date.dayofweek
but that gives an error :AttributeError: 'Series' object has no attribute 'date'
You are trying to work with string text to go to date? The date is in the index. I'm not sure if you have that in datetime yet, but let's assume it's just a string. Convert the index to datetime (timestamp).
df.index = pd.to_datetime(df.index)
print(df)
Day
Date
2011-01-26 Wednesday
2011-03-02 Wednesday
2011-04-12 Tuesday
2011-04-14 Thursday
2011-04-22 Friday
2020-05-25 Monday
2020-10-02 Friday
2020-11-16 Monday
2020-11-30 Monday
2020-12-25 Friday
But the Day column is still just a string. We can get the name of the day from the date using day_name() and setting it to a column.
df["Day_Name"] = df.index.day_name()
print(df)
Day Day_Name
Date
2011-01-26 Wednesday Wednesday
2011-03-02 Wednesday Wednesday
2011-04-12 Tuesday Tuesday
2011-04-14 Thursday Thursday
2011-04-22 Friday Friday
2020-05-25 Monday Monday
2020-10-02 Friday Friday
2020-11-16 Monday Monday
2020-11-30 Monday Monday
2020-12-25 Friday Friday
If you want the index to have the days.
df.index = df.index.day_name()

how to get the hours of the day, when hours is column to row in sql?

I have this data in my table:
Class Monday Tuesday Wednesday Thursday Friday
--------------------------------------------------------------------
class 1 8:00 12:00 8:00 8:00 10:00
class 2 7:00 15:00 7:00 NULL 7:00
class 3 11:00 11:00 12:00 NULL NULL
And I need to get the information as follows
Class Day Hour
--------------------------------------------------------------------
class 1 Monday 8:00
class 1 Tuesday 12:00
class 1 Wednesday 8:00
class 1 Thursday 8:00
class 1 Friday 10:00
class 2 Monday 7:00
class 2 Tuesday 15:00
class 2 Wednesday 7:00
class 2 Friday 7:00
class 3 Monday 11:00
class 3 Tuesday 11:00
class 3 Wednesday 12:00
Thanks for your answers and help guys, I really appreciate
Note: the result of the query will be displayed in an excel
What you need is an operation called UNPIVOT, which rotates columns to rows. You can produce the result you want with a query like this one, assuming you are using SQL Server:
SELECT Class, Day, Hour
FROM classes UNPIVOT (Hour FOR Day IN (Monday, Tuesday, Wednesday, Thursday, Friday)) u
Select *
From table
Order by Class, Monday, Tuesday, Wednesday, Thursday, Friday

Oracle SQL - Same day last year (leap year proof)

I'm looking to find the same day last year in oracle sql. For example Wednesday, March 16, 2016 would be Wednesday, March 18, 2015 for last year. So the closest day.
The following code worked good until the current leap year and broke after Feb 29th 2016.
this was my old statement which does not work for all dates:
NEXT_DAY(TRUNC(ADD_MONTHS(date, -12), 'iw')-2, TO_CHAR(date, 'DY'))
Simply subtract 7*52 = 364 days instead :-)
I think this may be correct
SQL Test:
WITH data
AS ( SELECT SYSDATE - (LEVEL - 1) this_year_date,
TO_NUMBER (TO_CHAR (SYSDATE - (LEVEL - 1), 'D'))
this_year_day_of_week,
ADD_MONTHS (SYSDATE - (LEVEL - 1), -12) last_year_date,
TO_NUMBER (
TO_CHAR (ADD_MONTHS (SYSDATE - (LEVEL - 1), -12), 'D'))
last_year_day_of_week
FROM DUAL
CONNECT BY LEVEL <= 300),
crunching
AS (SELECT data.*,
(CASE
WHEN this_year_day_of_week > last_year_day_of_week
THEN
this_year_day_of_week - last_year_day_of_week
WHEN this_year_day_of_week = last_year_day_of_week
THEN
0
ELSE
last_year_day_of_week - this_year_day_of_week
END)
math
FROM data)
SELECT TO_CHAR (crunching.this_year_date, 'yyyy-MM-dd Day') ty_date,
math,
(CASE
WHEN math = 0
THEN
TO_CHAR (last_year_date, 'yyyy-MM-dd Day')
WHEN math > 2
THEN
TO_CHAR ( (last_year_date - math) + 7, 'yyyy-MM-dd Day')
ELSE
TO_CHAR (last_year_date + math, 'yyyy-MM-dd Day')
END)
final_answer
FROM crunching
SQL Fiddle: http://sqlfiddle.com/#!4/9eecb7d/18211
Output:
TY_DATE MATH FINAL_ANSWER
2016-03-17 Thursday 2 2015-03-19 Thursday
2016-03-16 Wednesday 2 2015-03-18 Wednesday
2016-03-15 Tuesday 2 2015-03-17 Tuesday
2016-03-14 Monday 5 2015-03-16 Monday
2016-03-13 Sunday 5 2015-03-15 Sunday
2016-03-12 Saturday 2 2015-03-14 Saturday
2016-03-11 Friday 2 2015-03-13 Friday
2016-03-10 Thursday 2 2015-03-12 Thursday
2016-03-09 Wednesday 2 2015-03-11 Wednesday
2016-03-08 Tuesday 2 2015-03-10 Tuesday
2016-03-07 Monday 5 2015-03-09 Monday
2016-03-06 Sunday 5 2015-03-08 Sunday
2016-03-05 Saturday 2 2015-03-07 Saturday
2016-03-04 Friday 2 2015-03-06 Friday
2016-03-03 Thursday 2 2015-03-05 Thursday
2016-03-02 Wednesday 2 2015-03-04 Wednesday
2016-03-01 Tuesday 2 2015-03-03 Tuesday
2016-02-29 Monday 5 2015-03-02 Monday
2016-02-28 Sunday 6 2015-03-01 Sunday
2016-02-27 Saturday 1 2015-02-28 Saturday
2016-02-26 Friday 1 2015-02-27 Friday
2016-02-25 Thursday 1 2015-02-26 Thursday
2016-02-24 Wednesday 1 2015-02-25 Wednesday
2016-02-23 Tuesday 1 2015-02-24 Tuesday
2016-02-22 Monday 1 2015-02-23 Monday
2016-02-21 Sunday 6 2015-02-22 Sunday
2016-02-20 Saturday 1 2015-02-21 Saturday
2016-02-19 Friday 1 2015-02-20 Friday
2016-02-18 Thursday 1 2015-02-19 Thursday
2016-02-17 Wednesday 1 2015-02-18 Wednesday
How about add_months( [date], -12 ) ?

how to get data until the next 1 number

I have a date table where I have assinged business days. I need to get business from, for example, 1-20 before the next number 1. How can I do that? Here is a smaller verion of my table:
Date Day BusinessDays
2015-05-01 Friday 1
2015-05-02 Saturday 2
2015-05-03 Sunday 2
2015-05-04 Monday 2
2015-05-05 Tuesday 3
2015-05-06 Wednesday 4
2015-05-07 Thursday 5
2015-05-08 Friday 6
2015-05-09 Saturday 7
2015-05-10 Sunday 7
2015-05-11 Monday 7
2015-05-12 Tuesday 8
2015-05-13 Wednesday 9
2015-05-14 Thursday 10
2015-05-15 Friday 11
2015-05-16 Saturday 12
2015-05-17 Sunday 12
2015-05-18 Monday 12
2015-05-19 Tuesday 13
2015-05-20 Wednesday 14
2015-05-21 Thursday 15
2015-05-22 Friday 16
2015-05-23 Saturday 17
2015-05-24 Sunday 17
2015-05-25 Monday 17
2015-05-26 Tuesday 17
2015-05-27 Wednesday 18
2015-05-28 Thursday 19
2015-05-29 Friday 20
*2015-05-30 Saturday 1
*2015-05-31 Sunday 1
*2015-06-01 Monday 1
*2015-06-02 Tuesday 2
*2015-06-03 Wednesday 3
I need to get data from 1 to 20 business days and don't include the numbers that starts again from one (for example exclude rows that have * in front). This needs to be dynamic. Since DayName will change for every number so I can't include that in my where clause.
Let me assume that you have a date in mind, so you want everything from that date to the next "1".
select t.*
from datetable t
where t.date >= '2015-05-01' and
t.date < (select min(t2.date)
from datetable t2
where t2.date > '2015-05-01' and
t2.businessdays = 1
);

sql code to print all the mondays of the year 2012

2012
January
2/1/2012
9/1/2012
16/1/2012
23/1/2012
30/1/2012
February
6/2/2012
.
.
.
.
and so on till decemeber.
the dates mentioned are mondays..How do i get the output in this format?? please help
One option
SQL> ed
Wrote file afiedt.buf
1 select next_day(trunc(sysdate,'YYYY') + 7*(level-1), 'MON' )
2 from dual
3* connect by level <= 53
SQL> /
NEXT_DAY(
---------
02-JAN-12
09-JAN-12
16-JAN-12
23-JAN-12
30-JAN-12
06-FEB-12
13-FEB-12
20-FEB-12
27-FEB-12
05-MAR-12
12-MAR-12
<<snip>>
03-DEC-12
10-DEC-12
17-DEC-12
24-DEC-12
31-DEC-12
53 rows selected.
Query:
select distinct next_day(to_date('01-01-2012','mm-dd-yyyy')-1+level,'Monday') All_MON from dual
connect by level <= floor(to_date('12-31-2011','mm-dd-yyyy') - to_date('01-01-2011','mm-dd-yyyy'))
order by All_MON;
Output:
01/02/2012 MONDAY
01/09/2012 MONDAY
01/16/2012 MONDAY
01/23/2012 MONDAY
01/30/2012 MONDAY
02/06/2012 MONDAY
02/13/2012 MONDAY
02/20/2012 MONDAY
02/27/2012 MONDAY
03/05/2012 MONDAY
03/12/2012 MONDAY
03/19/2012 MONDAY
03/26/2012 MONDAY
04/02/2012 MONDAY
04/09/2012 MONDAY
04/16/2012 MONDAY
04/23/2012 MONDAY
04/30/2012 MONDAY
05/07/2012 MONDAY
05/14/2012 MONDAY
05/21/2012 MONDAY
05/28/2012 MONDAY
06/04/2012 MONDAY
06/11/2012 MONDAY
06/18/2012 MONDAY
06/25/2012 MONDAY
07/02/2012 MONDAY
07/09/2012 MONDAY
07/16/2012 MONDAY
07/23/2012 MONDAY
07/30/2012 MONDAY
08/06/2012 MONDAY
08/13/2012 MONDAY
08/20/2012 MONDAY
08/27/2012 MONDAY
09/03/2012 MONDAY
09/10/2012 MONDAY
09/17/2012 MONDAY
09/24/2012 MONDAY
10/01/2012 MONDAY
10/08/2012 MONDAY
10/15/2012 MONDAY
10/22/2012 MONDAY
10/29/2012 MONDAY
11/05/2012 MONDAY
11/12/2012 MONDAY
11/19/2012 MONDAY
11/26/2012 MONDAY
12/03/2012 MONDAY
12/10/2012 MONDAY
12/17/2012 MONDAY
12/24/2012 MONDAY
12/31/2012 MONDAY