BigQuery does not allow you to select the daypart MONTH in DATEDIFF.
Is there any other way to do this in BigQuery.
I can get days difference using the following but not months.
SELECT
OrderID,
OrderDate,
STRING( YEAR ( OrderDate )) + '-' + STRING(MONTH ( OrderDate )) as order_month,
UserID,
FirstOrderDate
DATEDIFF( OrderDate, FirstOrderDate) as date_diff,
FROM [orders.orders]
WHERE FirstOrderDate > DATE_ADD(CURRENT_TIMESTAMP(), -1, 'YEAR')
With Standard SQL you can use date_diff:
#StandardSQL
select date_diff(current_date, date '2018-03-06', month)
With standard SQL date_diff could work, but if you get an error saying "DATE_DIFF does not support the MONTH date part at [n:m]code", that's because your it's timestamp rather than date. To solve this issue, first cast the timestamp to date, then use date_diff function.
For example:
DATE_DIFF(CAST(OrderDate AS DATE), CAST(FirstOrderDate AS DATE), month) AS DATE_DIF
How about this?
(12 * YEAR(t2) + MONTH(t2)) - (12 * YEAR(t1) + MONTH(t1))
+ IF (DAY(t2) >= DAY(t1), 0, -1)
Running it over a couple of examples, it looks like what you'd want:
SELECT
(12 * YEAR(t2) + MONTH(t2)) - (12 * YEAR(t1) + MONTH(t1))
+ IF (DAY(t2) >= DAY(t1), 0, -1)
FROM
(SELECT TIMESTAMP("2010-12-01") as t1, TIMESTAMP("2011-01-01") as t2), // 1
(SELECT TIMESTAMP("2010-12-02") as t1, TIMESTAMP("2011-01-01") as t2), // 0
(SELECT TIMESTAMP("2010-12-01") as t1, TIMESTAMP("2011-12-01") as t2), // 12
(SELECT TIMESTAMP("2010-10-21") as t1, TIMESTAMP("2015-01-10") as t2) // 50
Related
I am trying to select a table of every date for the last year.
In SQL Server, I can run something like this:
SELECT TOP (DATEDIFF(DAY, DATEADD(YEAR, - 1, GETDATE()), GETDATE()) + 1)
Date = CAST(DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY a.object_id) - 1, DATEADD(YEAR, - 1, GETDATE())) AS DATE)
FROM sys.all_objects a
It returns 1 column with 366 rows containing the dates from 1 year ago until now.
I am looking for something equivalent in SQLITE.
You can do it with a recursive CTE:
WITH cte AS (
SELECT DATE(CURRENT_DATE, '-1 year') date
UNION ALL
SELECT DATE(date, '+1 day')
FROM cte
WHERE date < CURRENT_DATE
)
SELECT * FROM cte;
See the demo.
You can also do this using an inline tally table
WITH L1(n) AS (
VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
),
L2(n) AS (
SELECT 1 FROM L1 a CROSS JOIN L1 b
)
SELECT DATE(CURRENT_DATE, (-ROW_NUMBER() OVER (ORDER BY 1) + 1) || ' days') AS date
FROM L2
LIMIT julianday(CURRENT_DATE) - julianday(DATE(CURRENT_DATE, '-1 year')) + 1;
db<>fiddle
For newer versions of SQLite you may want to add NOT MATERIALIZED to the CTEs.
I have the following query:
#standardSQL
SELECT distinct (grand_total/months) AS avg, ((grand_total/days)) AS
avg_day
FROM
(select count(searchint.id) as Total, (DATE_DIFF(DATE ({{DATE_END}}),
DATE ({{DATE_START}}), DAY)+1) AS days, ((12 * YEAR(TIMESTAMP({{DATE_END}})) +
MONTH(TIMESTAMP({{DATE_END}}))) - (12 * YEAR(TIMESTAMP({{DATE_START}}))
+ MONTH(TIMESTAMP({{DATE_START}}))) +1) AS months,
(select count(searchint.id) as Total
from `dbsearch`
where cast(replace(searchint.createdDate,'Z','')as DateTime) >=
cast({{DATE_START}} as DateTime)
and cast(replace(searchint.createdDate,'Z','')as DateTime) <=
cast(DATE_ADD(cast({{DATE_END}} as date), Interval 1 day ) as DateTime)) AS grand_total
from `dbsearch`
where cast(replace(searchint.createdDate,'Z','')as DateTime) >=
cast({{DATE_START}} as DateTime)
and cast(replace(searchint.createdDate,'Z','')as DateTime) <=
cast(DATE_ADD(cast({{DATE_END}} as date), Interval 1 day ) as DateTime)
group by date(cast(replace(searchint.createdDate,'Z','')as DateTime))
ORDER BY 2 DESC) AS groupby
However, when I try to run BigQuery it gives the following error:
Function not found: YEAR at [5:180]
I understand it's because I'm using standardSQL, but how do I make that difference from months using standardSQL?
To find difference in months between two dates you better to use DATE_DIFF()
DATE_DIFF(DATE_END, DATE_START, MONTH)
StandardSQL in BigQuery supports the ISO/ANSI-standard function for extracting date parts. This is extract():
You want:
extract(year from <datecol>)
extract(month from <datecol>)
This is explained in the documentation.
I'm trying to create a query to only return data where date is minus 3 days from the current date. I've tried:
date <= DATE_ADD(CURRENT_DATE(), -3, 'DAY')
But this returns Error: Expected INTERVAL expression
See WHERE clause in below example
#standardSQL
WITH yourTable AS (
SELECT i, date
FROM UNNEST(GENERATE_DATE_ARRAY('2017-04-15', '2017-04-28')) AS date WITH OFFSET AS i
)
SELECT *
FROM yourTable
WHERE date <= DATE_SUB(CURRENT_DATE(), INTERVAL 3 DAY)
-- ORDER BY date
Btw, in case if you are still with Legacy SQL - see below example
#legacySQL
SELECT *
FROM -- yourTable
(SELECT 1 AS id, DATE('2017-04-20') AS date),
(SELECT 2 AS id, DATE('2017-04-21') AS date),
(SELECT 3 AS id, DATE('2017-04-22') AS date),
(SELECT 4 AS id, DATE('2017-04-23') AS date),
(SELECT 5 AS id, DATE('2017-04-24') AS date),
(SELECT 6 AS id, DATE('2017-04-25') AS date)
WHERE TIMESTAMP(date) <= DATE_ADD(TIMESTAMP(CURRENT_DATE()), -3, 'DAY')
-- ORDER BY date
This works with a string formatted date.
DATE(TIMESTAMP(date)) <= DATE_SUB(CURRENT_DATE(), INTERVAL 3 DAY)
Just tested this and seems to work.
I added this :
and DATE(TIMESTAMP(datevalue)) >= DATE_SUB(CURRENT_DATE(), INTERVAL 21 DAY)
and managed to get all records greater than last 21 days worth. Only thing I changed from #ericbrownaustin 's code was changed the 'date' in the first piece of code in the second set of parenthesis.
I have the following query which displays a table with date:
SELECT *
FROM [Db].[dbo].[btotals]
ORDER BY [Date] DESC
Which displays:
Date
06/07/2014
05/31/2014
05/24/2014
05/17/2014
05/10/2014
05/03/2014
If I pick SELECT TOP 1 will give me the first row. How can I modify my query so I get the week prior to last week? In this case the 5/31/14 row?
If your dates are always a week apart, and you just want the second row you can use ROW_NUMBER():
SELECT Date
FROM ( SELECT Date,
RowNumber = ROW_NUMBER() OVER(ORDER BY Date DESC)
FROM [Db].[dbo].[btotals]
) AS d
WHERE d.RowNumber = 2;
Otherwise you can use the following to get the saturday of 2 weeks ago:
SELECT DATEADD(DAY, -((DATEPART(WEEKDAY, GETDATE()) + ##DATEFIRST) % 7) - 7, CAST(GETDATE() AS DATE));
Then select your first date that is on or after that:
SELECT TOP 1 Date
FROM [Db].[dbo].[btotals]
WHERE Date >= DATEADD(DAY, -((DATEPART(WEEKDAY, GETDATE()) + ##DATEFIRST) % 7) - 7, CAST(GETDATE() AS DATE))
ORDER BY Date;
This should also work, if you are trying to select the second date, Though Gareth's approach of using ROW_NUNMBER is a better one.
SELECT TOP 1 *
FROM (
SELECT TOP 2 *
FROM [Db].[dbo].[btotals]
ORDER BY [Date] DESC
) as X
ORDER BY Date ASC
Another approach:
SELECT TOP 1 *
FROM [Db].[dbo].[btotals]
WHERE [Date] < (SELECT MAX([Date]) FROM [Db].[dbo].[btotals])
ORDER BY [Date] DESC
I'm using this to compare Year and month, but it failing when month is less than current month even though the year is greater than current year
SELECT * FROM DUMMY_TABLE WHERE
YEAR(PREV_ELIG_REV_DT) >= YEAR(CURRENT TIMESTAMP)
AND MONTH(PREV_ELIG_REV_DT) >= MONTH(CURRENT TIMESTAMP)
You could add and extra condition to match the situation when the YEAR is equal..
SELECT *
FROM DUMMY_TABLE
WHERE
YEAR(PREV_ELIG_REV_DT) > YEAR(CURRENT TIMESTAMP)
OR ( YEAR(PREV_ELIG_REV_DT) = YEAR(CURRENT TIMESTAMP)
AND MONTH(PREV_ELIG_REV_DT) >= MONTH(CURRENT TIMESTAMP))
UPDATE
As #Clockwork-Muse said, an alternative approach that may yield better performance would be to get the beginning of the current month and compare against that:
SELECT *
FROM DUMMY_TABLE
WHERE
PREV_ELIG_REV_DT >= (CURRENT DATE - (DAY(CURRENT DATE)-1) DAYS)
try this
SELECT * FROM DUMMY_TABLE
WHERE
YEAR(PREV_ELIG_REV_DT)*100 + MONTH(PREV_ELIG_REV_DT)
>= YEAR(CURRENT TIMESTAMP) * 100 + MONTH(CURRENT TIMESTAMP)