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.
Related
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 got a date that I want to find the all records in the past that got the same month and day.
The problem accrues when there is no such date in the same year. For example, the 29th February.
My goal is to get the nearest date from below the date that does not exist.
This is my currently query with the date 2012-02-29:
SELECT date, amount
FROM table_name
WHERE
EXTRACT(MONTH FROM date) = EXTRACT(MONTH FROM DATE('2012-02-29') )
AND EXTRACT(DAY FROM date) = EXTRACT(DAY FROM DATE('2012-02-29') )
AND date < '2012-02-29'
ORDER BY date DESC LIMIT 10;
If I understand correctly, you want one date per year with the property that that day is nearest to the given date.
I would suggest using distinct on:
select distinct on (date_trunc('year', date)) t.*
from table_name t
order by date_trunc('year', date),
abs(date_part('day, (date -
(date '2012-02-29' -
(extract(year from date '2012-02-29') - extract(year from date)) * interval '1 year'
)
)
)
)
);
EDIT:
An example of working code:
select distinct on (date_trunc('year', date)) t.*
from table_name t
order by date_trunc('year', date),
abs(date_part('day', date - (date '2012-02-29' -
((extract(year from date '2012-02-29') - extract(year from date)) * interval '1 year')
)
))
So, I have a query that uses GETDATE() in WHERE and HAVING clauses:
SELECT GETDATE(), COUNT(*) FROM (
SELECT 1 FROM events
WHERE (event_time > (GETDATE() - interval '25 hours'))
GROUP BY id
HAVING MAX(event_time) BETWEEN (GETDATE() - interval '25 hours') AND (GETDATE() - interval '24 hours')
)
I'm basically trying to find the number of unique ids that have their latest event_time between 25 and 24 hours ago with respect to the current time.
The problem: I have another table query_dts which contains one column containing timestamps. Instead of running the above query on the current time, using GETDATE(), I need to run in on the timestamp of every entry of the query_dts table. Any ideas?
Note: I'm not really storing query_dts anywhere. I've created it like this:
WITH query_dts AS (
SELECT (
DATEADD(hour,-(row_number() over (order by true)), getdate())
) as n
FROM events LIMIT 48
),
which I got from here
How about avoiding the generator altogether and instead just splitting the intervals:
SELECT
dateadd(hour, -distance, getdate()),
count(0) AS event_count
FROM (
SELECT
id,
datediff(hour, max(event_time), getdate()) AS distance
FROM events
WHERE event_time > getdate() - INTERVAL '2 days'
GROUP BY id) AS events_with_distance
GROUP BY distance;
You can use a JOIN to combine the two queries. Then you just need to substitute the values for your date expression. I think this is the logic:
WITH query_dts AS (
SELECT DATEADD(hour, -(row_number() over (order by true)), getdate()) as n
FROM events
LIMIT 48
)
SELECT d.n, COUNT(*)
FROM (SELECT d.n
FROM events e JOIN
query_dts d
WHERE e.event_time > d.n
GROUP BY id
HAVING MAX(event_time) BETWEEN n - interval '25 hours' AND n
) i;
Here's what I ended up doing:
WITH max_time_table AS
(
SELECT id, max(event_time) AS max_time
FROM events
WHERE (event_time > GETDATE() - interval '74 hours')
GROUP BY id
),
query_dts AS
(
SELECT (DATEADD(hour,-(row_number() over (ORDER BY TRUE) - 1), getdate()) ) AS n
FROM events LIMIT 48
)
SELECT query_dts.n, COUNT(*)
FROM max_time_table JOIN query_dts
ON max_time_table.max_time BETWEEN (query_dts.n - interval '25 hours') AND (query_dts.n - interval '24 hours')
GROUP BY query_dts.n
ORDER BY query_dts.n DESC
Here, I selected 74 hours because I wanted 48 hours ago + 25 hours ago = 73 hours ago.
The problem is that this isn't a general-purpose way of doing this. It's a highly specific solution for this particular problem. Can someone think of a more general way of running a query dependent on GETDATE() using a column of dates in another table?
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
How can you get today's date and convert it to 01/mm /yyyy format and get data from the table with delivery month 3 months ago? Table already contains delivery month as 01/mm/yyyy.
SELECT *
FROM TABLE_NAME
WHERE Date_Column >= DATEADD(MONTH, -3, GETDATE())
Mureinik's suggested method will return the same results, but doing it this way your query can benefit from any indexes on Date_Column.
or you can check against last 90 days.
SELECT *
FROM TABLE_NAME
WHERE Date_Column >= DATEADD(DAY, -90, GETDATE())
Latest Versions of mysql don't support DATEADD instead use the syntax
DATE_ADD(date,INTERVAL expr type)
To get the last 3 months data use,
DATE_ADD(NOW(),INTERVAL -90 DAY)
DATE_ADD(NOW(), INTERVAL -3 MONTH)
I'd use datediff, and not care about format conversions:
SELECT *
FROM mytable
WHERE DATEDIFF(MONTH, my_date_column, GETDATE()) <= 3
Last 3 months
SELECT DATEADD(dd,DATEDIFF(dd,0,DATEADD(mm,-3,GETDATE())),0)
Today
SELECT DATEADD(dd,DATEDIFF(dd,0,GETDATE()),0)
Last 3 months record
SELECT *, DATEDIFF(NOW(),`created_at`)as Datediff from `transactions` as t having Datediff <= 90