Extract All the Dates in a Calendar Month in yyyy-mm-dd format and store them in a new field - teradata-sql-assistant

I have a table that Looks like below. This table has multiple Accounts and corresponding to each account there is a issue_date
Input Table
ACCT_I Issue_date
A1 2004-05-16
A2 2008-02-25
......
Output Table
I want an output table, to list down all the dates of the month in which the issue occured i.e. for an Account A1 issue occured in May-2004, so next to A1, I want a field date_key that has dates from 2004-05-01 to 2004-05-31 in vertical manner i.e. something like below
ACCT_I Date_Key
A1 2004-05-01
A1 2004-05-02
A2 2004-05-03
and so on............
Simillary for A2, I want Date_Key to take values from 2008-02-01 to 2008-02-28. The query should also tackle leap years for February Month.
I am doing this exercise in Teradata.
I am new to Teradata, do not have any idea as to how to proceed. Please help.

Related

Breaking Up a Date Range by Individual Dates

I have a table with the following features: Invoice ID, billing_period_start, billing_period_end, and items_purchased during that period.
I'm looking to break out a date range by individual dates. A date range can be contained within one month, but it can also be spread across two months, unequally. This will effectively create many more records than are currently in the table. Once I have done that, I need to breakout the amount of purchased items equally among that dates of the daterange.
billing_period_start billing_period_end
-------------------- ------------------
2010-03-05 2010-03-07
2010-04-29 2010-05-05
2010-06-29 2006-08-12
billing_date
------------
2010-03-05
2010-03-06
2010-03-07
2010-04-29
2010-04-30
2010-05-01
...
2010-05-05
2010-06-29
2010-06-30
...
2010-08-12
Now that the date range is broken into individual dates, I need to take the items_purchase and divide it by the number of the days in the billing period for each date, so that I have the items_purchase_per_date.
select
invoice_line_id AS invoice_id
,items_purchased
,billing_period_start
,billing_period_end
,date_from_parts(YEAR(billing_period_start), MONTH(billing_period_start), 1) AS period1_month_start
,last_day(month_start, month) AS period1_month_end
,datediff(day, billing_period_start, billing_period_end) + 1 AS billing_period_length
from "INVOICE_DATA"
order by 1;
I'm running this on Snowflake, but can easily convert from mySQL, if someone knows that DBMS better.
The best way to handle this in a data warehouse is using a date dimension table. That is, a table that contains all the dates you need for analysis, plus any date attributes that are interesting as well, such as which week/month/quarter etc the date belongs to and so on.
Once you have table with unique rows for all relevant dates, you can more easily tackle date spine challenges like this.
For example, for your case you'd write (assuming dates is the name of your date dimension and calendar_date the name of the column containing the unique dates:
select
d.calendar_date,
i.*
from
dates d
join
invoice_data i
on d.calendar_date between i.billing_period_start and i.billing_period_end
Now you have one row per date between those start/end dates and you can do your daily billing allocation.

Mysql Function multiple entries in one cell

So I'm working on a schedule system for my job a basically i wanted to know if there is a way where mysql can do something like:
|Monday |tuesday|wendsday|total
|Dan |5am-7am |7am-6pm|6am-11am|
11am-2pm| |2pm-7pm |
5pm-12am|
where i can enter multiple shifts on 1 day for each person in the same cell if needed instead of the name repeating several times like:
Dan|5-4|
Dan|6-8|
and if there is a function to calculate total time in one cell with multiple shifts
There is a way (representing the data as string), but you wouldn't want to do this - you will loose all calculations, searches etc.
You should not try to represent the data in the database exactly as how it looks on paper.
I would make a table like this:
ShiftID|Person|StartTime|EndTime
Making StartTime & EndTime columns of type DATETIME, you will store not only the HH:mm of a shift's start, but also the day. This is helpful when you have a shift which starts on one day and ends in the next, like starting on Monday 2017-05-15 23:00 and ending on Tuesday 2017-05-16 02:00.
You can extract the date only from this filed using MySQL DATE() function and select only those entires which start OR end on this day.
To calculate the shift's duration you can use MySQL function TIMESTAMPDIFF()
You can even use DAYOFWEEK() to get if it is Monday, Tuesday, etc.
About duplicating the person's name - I would make another table, which will match users with their data to IDs an use ID in the column Person, but for a starter and if your data is not big and if speed is not an issue and if typo errors (like Den instead of Dan) are not a problem ... you could use the name directly in this table.
After storing the data in a table like this you could represent it as you wish in HTML (or print).
You can create a third table with the following columns:
person_id int,
start_time datetime,
end_time datetime
Where person_id would be foreign key to Person table and start_time and end_time would be datetime columns. You can then store multiple records for a person in this table and use MySQL's date functions with GROUP BY to generate the report similar to the one in question.

Spreadsheet - From A Table Of Names And Birth Dates Pull A List Of Names As Of A Reference Date And There About

I have posted this question before, and got half-solution. Pls have a look at this link to get an idea.
The solution was almost achieved, but the function posted by Mr. Yogi has some errors and now Mr. Yogi is unreachable.
Let me explain it once again.
Things i wish to achieve : I have a list of members and their birthdates, i am willing to enter this data manually. I am trying to create a sheet which can wish "happy birthday" to members having birthday today (current date) and a list of members having birthday in next 7 days (from current date). I can publish this sheet (particular cell range) on my webpage for the very purpose.
Have a look at sample sheet. Feel free to take a copy to edit.
Incase you are not getting it, Let me explain everything once again
A1 & B1 has headings called NAMES & BIRTHDATES respectively.
A2 to A2000 has names (i.e user1, user2, user3 and so on)
& B2 to B2000 has birthdates in DD/MM/YYYY format (i.e 13-12-1980, 25-05-1990, 31-2-1984) years can be anywhere between 1950 to year 2000.
(i have this names and birthdates data with me, i will put it manually one by one or i can publish a spreadsheet form online for my users). So No formulas here in column A & B.
D2 - this cell has no formula, but we can input date here (this is just for checking sake, so whenever my sheet gets its final formula, i can check it with any date i wish)
E2 - this cell has formula, it checks if D2 has some date, if yes then it pulls d2 data, if d2 is empty, it shows current date by this formula
=if(D2="",today(),D2)
D6 - this cell has formula, it checks the whole list of dates in B2 to B2000 or can say whole column B, if any date matches with E2 (which is current date, or the date written by me in D2) then it pulls out name(s) of that user(s) and shows it with commas. For example if value in E2 is 16-11-2014 then D6 formula check this date with full column B, if it finds any match, it pulls the name in same row of column A and shows it here. And if no matches found, it shows "No Members Birthday Today". Formula for D6 is
=if(iferror("Happy Birthday to "&join(", ",filter(A:A,month(B:B)=month( E2),day(B:B)=day(E2))))=0,"No Member's Birthday Today",iferror("Happy Birthday to "&join(", ",filter(A:A,month(B:B)=month( E2),day(B:B)=day(E2)))))
E9 - This cell has no formula, its there just to put some figure (number of days) which can be used in formula of D11. For example if we enter number "7" in cell E9, then the formula in D11 will sort list of users having birthdays in upcoming 7 days (from current date or from date entered in D2). For example if D2 is empty, E2 will show current date, say its 16-11-2014, If we put number 7 in E9 then D11 formula searches for users/birth dates having birthday in upcoming 7 days (17-11-2014 to 23-11-2014) and display list of users with dates in D11.
Now here comes the MONSTER
D11 - This cell has formula, infact most important formula for this sheet (which is currently not perfect).
Say if E2 has a date of 16-11-2014 & E9 has number 7. Then D11 formula should check/search next 7 days dates in column B and if it finds any match, it should pull username from same row (from column A) and should display something like this
17/11 - user3, user888, user 75. (these user's birthday is on 17/11, which is next day from current date (upcoming day))
18/11 - user22, user975, user 666, user 1091 (these user's have birthday on 18/11, which is day after tomorrow from current date.)
20/11 - user99 (this user birthday on 20/11)
...
Above list can go till maximum 7 rows or less, because i have given range of 7 days in cell E9.
Now, Mr.Yogi helped me in D11 formula, but formula is not complete, it has some errors, Formula for D11 is
=ArrayFormula(substitute(trim(transpose(split(concatenate({(if(unique(ArrayFormula(filter(TEXT(B:B,"dd/mm"),date(0,month(B:B),day(B:B))>date(0,month(E2),day(E2)),date(0,month(B:B),day(B:B))<=date(0,month(E2),day(E2)+E9))))=transpose(ArrayFormula(filter(TEXT(B:B,"dd/mm"),date(0,month(B:B),day(B:B))>date(0,month(E2),day(E2)),date(0,month(B:B),day(B:B))<=date(0,month(E2),day(E2)+E9)))),transpose((query({A:A,text(B:B,"dd/mm")},"select Col1 where '"&join(", ",unique((filter(TEXT(B:B,"dd/mm"),date(0,month(B:B),day(B:B))>date(0,month(E2),day(E2)),date(0,month(B:B),day(B:B))<=date(0,month(E2),day(E2)+E9)))))&"' contains Col2")) ),))&" ",transpose(split(rept(Char(10)&char(9),countunique((filter(TEXT(B:B,"dd/mm"),date(0,month(B:B),day(B:B))>date(0,month(E2),day(E2)),date(0,month(B:B),day(B:B))<=date(0,month(E2),day(E2)+E9))))),char(9)))}),char(10))))," ",", ")&" - "&unique((filter(TEXT(B:B,"dd/mm"),date(0,month(B:B),day(B:B))>date(0,month(E2),day(E2)),date(0,month(B:B),day(B:B))<=date(0,month(E2),day(E2)+E9)))))
Above formula has some errors, it doesn't works if we enter year ending dates like 31-12-2014 in D2 and range of 7 days in E9. Pls fix this so it can show upcoming birthdays of users having birthday in upcoming 7 days (January)
Another error I found was, if we enter dates like 29-02-2014, D11 says #N/A why so ! All other dates are working fine, then why animosity with february last day.
2 more things i wish to change,
1. D11 should show date first and names afterwards (instead of names first and dates afterwards)
Like This
15-04 - user1, user2
21-04 - user3, user4
27-04 - user11, user6, user88, user509
I think this will be easy for you, just changing positions (though i dont know, how to do it :) )
2. Dates in cell D11 are not in order, Pls fix this. it should be like this
15-04 - user1, user2
21-04 - user3, user4
27-04 - user11, user6, user88, user509
and not like this
21-04 - user3, user4
15-04 - user1, user2
27-04 - user11, user6, user88, user509
Query & Explanation over.
Few suggestions (ideas) coming in my mind:
#2 would be easy i think, I dont know how to do it, But by anyway if we can sort column B by dates (ascending) (or by pulling and sorting it to column C). As far as i can understand, i think YEAR has no role in any formula, formula works only on mm (month) and dd (date), so why not to sort only dd/mm in column C and then pull it to D11 formula. Well this is just a guess
Thanks for all your time and efforts.
Waiting ...
This will not list the 29th February if it is not a valid date in the next E9 days (so people born on this day would simply miss out ~75% of the time). I'll await the OP's advice on how this should be managed.
=ArrayFormula(TRANSPOSE(REGEXREPLACE(TRIM(QUERY(FILTER({TEXT(E2+COLUMN( OFFSET(A1,,,1,E9)),"dd/mm")&" - ";REPT(A2:A&", ",TEXT(B2:B,"dd/mm")=TEXT(E2+COLUMN( OFFSET(A1,,,1,E9)),"dd/mm"))},MATCH(TEXT(E2+COLUMN(OFFSET(A1,,,1,E9)),"dd/mm"), TEXT(B2:B,"dd/mm"),0)),,ROWS(A2:A)+1)),",$","")))
I will (attempt) to explain the logic if requested, but at the risk of a rap over the knuckles, I'll refrain for now.

Querying Comma Delimited Values in MySQL

I need a way to query a collection of data. I have a list of recent activity dates each stored in 1 row per user. Each row has a field of loginDates which consists of a comma separated list of timestamps.
What i need to do is run reports on this date to find people active since XXXXXX timestamp. The problem is the fact it's comma separated means i can't query it uses methods i know.
Here is an example row
id userID accessDates
2 6 1399494405,1399494465,1399494525,1399494585,1399494623
What i want to achieve in plain text
SELECT all_fields FROM accessTable WHERE accessDate > YESTERDAY
ALSO These dates may however span over several hundreds of days with hundreds of timestamps in the field.
Assuming the TimeStamp values are in order as your data sample shows, if any of the TimeStamp values in the string are greater than a given date, then the latest one would be greater than that value as well. So you only need the latest TimeStamp value to meet your requirement:
SET #Yesterday =
UNIX_TIMESTAMP(DATE_ADD(DATE(CURRENT_TIMESTAMP()),INTERVAL -1 DAY));
SELECT *
FROM accessTable
WHERE CAST(RIGHT(accessDates,10) AS UNSIGNED) > #Yesterday;
If you want to query each of those TimeStamps individually, the best solution is to put them into a single table column with a userid:
userID accessDate
------ ----------
6 1399494405
6 1399494465
6 1399494525
6 1399494585
6 1399494623

Prompting user for 2 dates and generating table with 0-23 hours for date range

I need to prompt the user for 2 dates, e.g. 1/1/2008 , 2/5/2008 , and generate a two column report with all 0-23 hours for each date in the range. The date being in the first column and the hour being in the second column.
1/1/2008 0
1/1/2008 1
1/1/2008 3
[...etc]
2/4/2008 23
You could create an hours table with 24 rows containing values 0-23, then do a cross join (no links) with each date in the range entered.
You can do something like that by doing a simple join on two temporary tables
SELECT tmpdate.day,tmp hour.time
FROM tmphour, tmpdate
ORDER BY tmpdate.day, tmphour.time;
tmphour containing a list hours 0-23 and tmpdate containing a list of dates