I'm attempting to convert a string to a timestamp within Bigquery. The question is really simple, how do I convert this string Jan 30 2016 12:00AM or Aug 9 2015 12:00AM to date?
I have tried referring to the Bigquery documentation but it didn't seem to work:
(https://cloud.google.com/bigquery/docs/reference/standard-sql/date_functions#parse_date)
select PARSE_DATE('%b %e %E4Y', 'Jan 30 2016 12:00AM')
select PARSE_DATE('%b %e %E4Y', 'Aug 9 2015 12:00AM')
Your input string is actually a timestamp, not a date, because it has a time component at the end. So, consider using PARSE_TIMESTAMP instead:
SELECT PARSE_TIMESTAMP('%b %e %E4Y %I:%M%p', 'Jan 30 2016 12:00AM') AS ts_out
FROM yourTable;
This would return a timestamp based on the input string. If you really want a date, you could cast the above to date, or you could just use LEFT on the string input to restrict to only the date portion:
SELECT PARSE_DATE('%b %e %E4Y', LEFT('Jan 30 2016 12:00AM', 11)) AS ts_out
FROM yourTable;
Below is for BigQuery Standard SQL
SELECT DATE(PARSE_TIMESTAMP('%b %e %Y %R%p', ts))
You can test it with dummy data as in below example
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'Jan 30 2016 12:00AM' ts UNION ALL
SELECT 'Aug 9 2015 12:00AM' UNION ALL
SELECT 'Aug 9 2015 12:00AM'
)
SELECT ts, DATE(PARSE_TIMESTAMP('%b %e %Y %R%p', ts)) date_from_ts
FROM `project.dataset.table`
with result
Row ts date_from_ts
1 Jan 30 2016 12:00AM 2016-01-30
2 Aug 9 2015 12:00AM 2015-08-09
3 Aug 9 2015 12:00AM 2015-08-09
Related
I have a table named nifty_50 with the below two columns.
Date Close
Apr 07, 2022 17,763.40
Apr 06, 2022 17,807.65
Apr 05, 2022 17,957.40
Apr 04, 2022 18,053.40
Apr 01, 2022 17,670.45
Mar 31, 2022 17,464.75
I am trying to add another column which says the day name of the Date column.
Expected Output:
Date Close Day_name
Apr 07, 2022 17,763.40 Thursday
Apr 06, 2022 17,807.65 Wednesday
Apr 05, 2022 17,957.40 Tuesday
Apr 04, 2022 18,053.40 Monday
Apr 01, 2022 17,670.45 Friday
Mar 31, 2022 17,464.75 Thursday
I tried doing
select date, close, datename(date ,getdate()) as day_name, from nifty_50;
The above code doesn't work and all the other codes which i googled and tried also don't work. I know this is a simple code. can someone please help me with this?
Use the TO_CHAR function with the Day format model.
select "DATE",
close,
TO_CHAR("DATE", 'fmDay') as day_name
from nifty_50;
Note: fmDay will strip trailing spaces from the day names (otherwise the days will all be output as strings of length equal to the longest day name padded with trailing spaces).
Note 2: DATE is a reserved word in Oracle and cannot be used as an unquoted identifier. It is better practice to pick a different identifier instead of using reserved words.
Which, for the sample data:
CREATE TABLE nifty_50 ("DATE", Close) AS
SELECT DATE '2022-04-07', 17763.40 FROM DUAL UNION ALL
SELECT DATE '2022-04-06', 17807.65 FROM DUAL UNION ALL
SELECT DATE '2022-04-05', 17957.40 FROM DUAL UNION ALL
SELECT DATE '2022-04-04', 18053.40 FROM DUAL UNION ALL
SELECT DATE '2022-04-01', 17670.45 FROM DUAL UNION ALL
SELECT DATE '2022-03-31', 17464.75 FROM DUAL;
Outputs:
DATE
CLOSE
DAY_NAME
2022-04-07 00:00:00
17763.4
Thursday
2022-04-06 00:00:00
17807.65
Wednesday
2022-04-05 00:00:00
17957.4
Tuesday
2022-04-04 00:00:00
18053.4
Monday
2022-04-01 00:00:00
17670.45
Friday
2022-03-31 00:00:00
17464.75
Thursday
db<>fiddle here
You can try below to fetch Day name:
DECLARE #DateVal DATE = '2022-07-04';
SELECT #DateVal As [Date],
DATENAME(WEEKDAY, #DateVal) AS [Day Name],
DATENAME(DW, #DateVal) AS [Day Name],
DATENAME(W, #DateVal) AS [Day Name];
I want to create a date column which would take 'year' and 'month' and give me a date starts from 1st
E_name s_date year month
a 01-08-2012 2012 MAR
a 23-06-2012 2010 DEC
a 19-03-2020 2020 DEC
a 14-02-2020 2020 MAR
b 27-12-2018 2018 DEC
REQUIRED OUTPUT
E_name s_date year month Date
a 01-08-2012 2012 MAR 01-03-2012
a 23-06-2012 2010 DEC 01-12-2010
a 19-03-2020 2020 DEC 01-12-2020
a 14-02-2020 2020 MAR 01-03-2020
b 27-12-2018 2018 DEC 01-12-2018
Concatenate the year and month columns and then use TO_DATE:
SELECT t.*,
TO_DATE(month || year, 'MONYYYY', 'NLS_DATE_LANGUAGE=American') AS "Date"
FROM table_name t
Which, for your sample data:
CREATE TABLE table_name (E_name, s_date, year, month) AS
SELECT 'a', DATE '2012-08-01', 2012, 'MAR' FROM DUAL UNION ALL
SELECT 'a', DATE '2012-06-23', 2010, 'DEC' FROM DUAL UNION ALL
SELECT 'a', DATE '2020-03-19', 2020, 'DEC' FROM DUAL UNION ALL
SELECT 'a', DATE '2020-02-14', 2020, 'MAR' FROM DUAL UNION ALL
SELECT 'b', DATE '2018-12-27', 2018, 'DEC' FROM DUAL;
Outputs:
E_NAME
S_DATE
YEAR
MONTH
Date
a
01-08-2012
2012
MAR
01-03-2012
a
23-06-2012
2010
DEC
01-12-2010
a
19-03-2020
2020
DEC
01-12-2020
a
14-02-2020
2020
MAR
01-03-2020
b
27-12-2018
2018
DEC
01-12-2018
db<>fiddle here
I have two tables: 'project' and 'project_status' in a BigQuery database...
project
Id Name
1 XXXX
2 YYYY
3 ZZZZ
project_status
project_id status_date status
1 2 Jan 2020 Good
2 4 Feb 2020 Bad
3 5 Feb 2020 On track
3 6 March 2020 Bad
I want to produce a monthly report of project status. The status of a project is not updated each month. In this case the most recent status entry up to the month end is taken as the latest status
Month Project Status
Jan 2020 XXXX Good
Feb 2020 XXXX Good
Mar 2020 XXXX Good
Jan 2020 YYYY null
Feb 2020 YYYY Bad
Mar 2020 YYYY Bad
Jan 2020 ZZZZ null
Feb 2020 ZZZZ On track
Mar 2020 ZZZZ Bad
For example, with project 'XXXX', there is no status update for Feb 2020 or March 2020, so the status is to be taken from the most recent status entry of 2 Jan 2020.
Any suggestions on how to build a SQL query to deliver this report?
Consider using GENERATE_DATE_ARRAY AND ARRAY_AGG:
WITH Months AS (
SELECT DATE_SUB(month, INTERVAL 1 DAY) AS last_day
FROM UNNEST(GENERATE_DATE_ARRAY('2020-02-01', '2020-04-02', INTERVAL 1 MONTH)) AS month
),
Projects as (
SELECT 1 AS Id, 'XXXX' AS Name UNION ALL
SELECT 2 AS Id, 'YYYY' AS Name UNION ALL
SELECT 3 AS Id, 'ZZZZ' AS Name
),
Project_Status as (
SELECT 1 AS project_id, PARSE_DATE('%e %b %Y', '2 Jan 2020') AS status_date, 'Good' AS status UNION ALL
SELECT 2, PARSE_DATE('%e %b %Y', '4 Feb 2020'), 'Bad' UNION ALL
SELECT 3, PARSE_DATE('%e %b %Y', '5 Feb 2020'), 'On track' UNION ALL
SELECT 3, PARSE_DATE('%e %b %Y', '6 March 2020'), 'Bad'
)
SELECT Projects.Name as Name, DATE_TRUNC(Months.last_day, MONTH) AS Month,
ARRAY_AGG(Project_Status.status ORDER BY status_date DESC)[OFFSET(0)] AS Status
FROM Projects
CROSS JOIN Months
LEFT JOIN Project_Status ON
Project_Status.project_id = Projects.id
AND Project_Status.status_date <= Months.last_day
GROUP BY Name, Month
The output is:
This query counts the amount of bottles we produce over a month and groups them by day. If there are no bottles produces that day then it is skipped from the output instead of returning 0 bottles produced. How can I return with the day's timestamp if there are no bottles produced? I heard the calendar table has to be used for this.
SELECT CONVERT(datetime,CAST(t_stamp AS DATE)), COUNT(bottles) AS 'Good Bottles'
FROM bottles
WHERE t_stamp
BETWEEN "any date"
AND "any date"
GROUP BY CAST(t_stamp AS DATE)
ORDER BY CAST(t_stamp AS DATE) ASC
Current Output:
Aug 12, 2019 12:00 am..................4302
Aug 13, 2019 12:00 am..................2302
Aug 17, 2019 12:00 am..................1302
Aug 18, 2019 12:00 am..................4302
Desired Output:
Aug 12, 2019 12:00 am..................4302
Aug 13, 2019 12:00 am..................2302
Aug 14, 2019 12:00 am..................0
Aug 15, 2019 12:00 am..................0
Aug 16, 2019 12:00 am..................0
Aug 17, 2019 12:00 am..................1302
Aug 18, 2019 12:00 am..................4302
You need to generate the days. A pretty simple method uses a recursive CTE:
WITH dates as (
SELECT CONVERT(date, "any date1") as dte
UNION ALL
SELECT DATEADD(day, 1, dte)
FROM dates
WHERE dte < "any date2"
)
SELECT d.dte, COUNT(bottles) AS GoodBottles
FROM dates d LEFT JOIN
bottles b
ON CAST(t_stamp as DATE) = d.dte
GROUP BY d.dte
ORDER BY d.dte ASC;
Notes:
If you have a calendar or tally table, then use that instead.
If the number of dates exceed 100, you need to add OPTION (MAXRECURSION 0).
COUNT(bottles) looks suspicious. Do you really intend SUM(bottles)?
Converting a column to a date and then to a datetime is also suspicious. It is unclear why you would want a datetime for the first column.
Here is my code:
select
(case when c.yr = 2019 and c.mon = 10 then 'October 2019'
when c.yr = 2019 and c.mon = 11 then 'November 2019'
when c.yr =2019 and c.mon = 12 then 'December 2019' end) as dae
from (
select substr(d,-4,4) as yr, substr(d,1,2) as mon
from
(select '10/11/2019' as d from dual) )c;
`
So I don't want to hard code the dates for the next 5 years, Is there a function that makes this easier.
Here is the Sample Input I want to try
10/11/2019
11/11/2019
12/11/2019
01/11/2020
Expected Output
October 2019
November 2019
December 2019
January 2020
You could use to_date() to turn your string to a date, and then convert it back to a string in the desired format with to_char():
to_char(to_date(d, 'mm/dd/yyyy'), 'Month yyyy')
Demo on DB Fiddle:
with t as (
select '10/11/2019' d from dual
union all select '11/11/2019' from dual
union all select '12/11/2019' from dual
union all select '01/11/2020' from dual
)
select to_char(to_date(d, 'mm/dd/yyyy'), 'Month yyyy') new_dt from t
| NEW_DT |
| :------------- |
| October 2019 |
| November 2019 |
| December 2019 |
| January 2020 |
Use connect by to generate as many dates as you want. Here the gen_dates CTE starts with your start_date and returns a total of 4 months per your example. To increase the number of months to generate, increase the number 4 to a higher number.
with gen_dates(date_in) as (
select add_months('11-OCT-2019', level -1) date_in
from dual
connect by level <= 4
)
select date_in, to_char(date_in, 'Month yyyy') date_out
from gen_dates;
DATE_IN DATE_OUT
--------- --------------
11-OCT-19 October 2019
11-NOV-19 November 2019
11-DEC-19 December 2019
11-JAN-20 January 2020
4 rows selected.