I have two event tables with timestamped data: Registered, Signed_In.
Both have rows such as: original_timestamp, user_id
I am trying to find out users who haven't signed in within 30 days after registering. I have used the following query but I cannot add a WHERE clause to it.
I tried a query but I am getting hourly difference, whereas I wanted days difference which is unsupported in BigQuery.
SELECT Signed_In.user_id, TIMESTAMP_DIFF(Registered.original_timestamp, Signed_In.original_timestamp, HOUR) AS days_difference
FROM `test_db.Signed_In` signed_in
JOIN `test_db.Registered` registered
ON Signed_In.user_id = Registered.user_id
GROUP BY 1,2
ORDER BY 2 DESC
WHERE days_difference > '30'
I am getting two columns: user_id, days_difference but the days_difference shows hours and my WHERE clause is rejected when I use it.
You can try this below code-
Note: Using Ordinal Position for GROUP BY and ORDER BY is not a good practice. Its always safe and standard to use the column names directly.
SELECT Signed_In.user_id,
TIMESTAMP_DIFF(Registered.original_timestamp, Signed_In.original_timestamp, HOUR) AS days_difference
FROM `test_db.Signed_In` signed_in
JOIN `test_db.Registered` registered
ON Signed_In.user_id = Registered.user_id
WHERE DATE_DIFF(Registered.original_timestamp, Signed_In.original_timestamp, Day) > '30'
GROUP BY 1,2
ORDER BY 2 DESC
Just replace HOUR to DAY in your query:
SELECT Signed_In.user_id, TIMESTAMP_DIFF(Registered.original_timestamp, Signed_In.original_timestamp, DAY) AS days_difference
Correct values are:
MICROSECOND
MILLISECOND
SECOND
MINUTE
HOUR
DAYOFWEEK
DAY
DAYOFYEAR
WEEK: Returns the week number of the date in the range [0, 53]. Weeks begin with Sunday, and dates prior to the first Sunday of the year are in week 0.
WEEK(<WEEKDAY>): Returns the week number of timestamp_expression in the range [0, 53]. Weeks begin on WEEKDAY. datetimes prior to the first WEEKDAY of the year are in week 0. Valid values for WEEKDAY are SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, and SATURDAY.
ISOWEEK: Returns the ISO 8601 week number of the datetime_expression. ISOWEEKs begin on Monday. Return values are in the range [1, 53]. The first ISOWEEK of each ISO year begins on the Monday before the first Thursday of the Gregorian calendar year.
MONTH
QUARTER
YEAR
ISOYEAR: Returns the ISO 8601 week-numbering year, which is the Gregorian calendar year containing the Thursday of the week to which date_expression belongs.
DATE
DATETIME
TIME
Related
select extract(week from current_date) is giving 16 but current ISO week is 17.
Is this a bug or am I doing something wrong? Last week it worked OK.
You might be looking for:
extract(isoweek from current_date)
As per the documentation:
WEEK: Returns the week number of the date in the range [0, 53]. Weeks begin with Sunday, and dates prior to the first Sunday of the year are in week 0.
ISOWEEK: Returns the ISO 8601 week number of the date_expression. ISOWEEKs begin on Monday. Return values are in the range [1, 53]. The first ISOWEEK of each ISO year begins on the Monday before the first Thursday of the Gregorian calendar year.
I am converting an old query from Legacy SQL to Standard SQL and noticed my report was off. I've traced it back to Legacy SQL and Standard SQL returning different weeks based off of a UNIX millisecond timestamp.
I was under the impression the Legacy SQL query was correct, but however, I'm curious to know the difference. It's not across all weeks, but enough to throw my report off significantly.
Here's an example:
#legacySQL
SELECT WEEK(MSEC_TO_TIMESTAMP(1470631859000)) AS sign_up_week;
Output: 33
#standardSQL
SELECT EXTRACT(WEEK FROM TIMESTAMP_MILLIS(1470631859000));
Output: 32
I've viewed the following documentation on the Legacy SQL reference:
WEEK(<timestamp>)
Returns the week of a TIMESTAMP data type as an integer between 1 and 53, inclusively.
Weeks begin on Sunday, so if January 1 is on a day other than Sunday, week 1 has fewer than 7 days and the first Sunday of the year is the first day of week 2.
And from the Standard SQL reference:
WEEK(<WEEKDAY>): Returns the week number of the date in the range [0, 53]. Weeks begin on WEEKDAY. Dates prior to the first WEEKDAY of the year are in week 0. Valid values for WEEKDAY are SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, and SATURDAY.
ISOWEEK: Returns the ISO 8601 week number of the date_expression. ISOWEEKs begin on Monday. Return values are in the range [1, 53]. The first ISOWEEK of each ISO year begins on the Monday before the first Thursday of the Gregorian calendar year.
How can I get my Standard SQL query to output the same week number as my Legacy SQL query? If not, which week number is correct? It does not appear I can get them to dovetail natively.
This is a bit subtle, but legacy and standard SQL handle weeks differently. In Legacy SQL:
Weeks begin on Sunday, so if January 1 is on a day other than Sunday, week 1 has fewer than 7 days and the first Sunday of the year is the first day of week 2.
In Standard SQL:
WEEK: Returns the week number of the date in the range [0, 53]. Weeks begin with Sunday, and dates prior to the first Sunday of the year are in week 0.
So, in Legacy SQL the first Sunday is week 2. In Standard SQL, the first Sunday is week 1.
Need help figuring out how to determine if the date is the same 'day' as today in teradata. IE, today 12/1/15 Tuesday, same day last year was actually 12/2/2014 Tuesday.
I tried using current_date - INTERVAL'1'Year but it returns 12/1/2014.
You can do this with a bit of math if you can convert your current date's "Day of the week" to a number, and the previous year's "Day of the week" to a number.
In order to do this in Teradata your best bet is to utilize the sys_calendar.calendar table. Specifically the day_of_week column. Although there are other ways to do it.
Furthermore, instead of using CURRENT_DATE - INTERVAL '1' YEAR, it's a good idea to use ADD_MONTHS(CURRENT_DATE, -12) since INTERVAL arithmetic will fail on 2012-02-29 and other Feb 29th leap year dates.
So, putting it together you get what you need with:
SELECT
ADD_MONTHS(CURRENT_DATE, -12)
+
(
(SELECT day_of_week FROM sys_calendar.calendar WHERE calendar_date = CURRENT_DATE)
-
(SELECT day_of_week FROM sys_calendar.calendar WHERE calendar_date = ADD_MONTHS(CURRENT_DATE, -12))
)
This is basically saying: Take the current dates day of week number (3) and subtract from it last years day of week number (2) to get 1. Add that to last year's date and you'll have the same day of the week as current date.
I tested this for all dates between 01/01/2010 and CURRENT_DATE and it worked as expected.
Why don't you simply subtract 52 weeks?
current_date - 364
The SQL below will get you to the abbreviated name for the day of week, it's cumbersome but it works across versions of Teradata.
SELECT CAST(CAST(ADD_MONTHS(CURRENT_DATE, -12) AS DATE FORMAT 'E3') AS CHAR(3)) AS LY_DayOfWeek
, CAST(CAST(CURRENT_DATE) AS DATE FORMAT 'E3') AS CHAR(3)) AS CY_DayOfWeek
Dates are internally represented at integers in Teradata as (Year-1900) * 100000 + (MONTH * 100) + DAY. You may be able to do some creative arithmetic to figure out that 12/1/2015 Tuesday was 12/2/2014 Tuesday last year.
I'm trying to create a SQL statement (in H2 Dialect) that creates a DATE which is
the tuesday in the "week-of-year" that is two weeks from the current week.
For example, given CURRENT_DATE() returns 2014-04-23, the date that I want would be 2014-04-08, which is the Tuesday in the week that is two weeks before the week the Date "2014-04-23" is in.
How can I express this with H2's Date and Time functions?
In sql-server I would do it like this
DECLARE #date DATE = GETDATE();
SELECT DATEADD(DAY,3-DATEPART(WEEKDAY,#date),DATEADD(WEEK,-2,#date))
Where '3' represents day of the week (Tuesday) and '-2' represents subtracting two weeks.
So now in h2 it is very similar
SELECT DATEADD('DAY',3-DAY_OF_WEEK(CURRENT_DATE()),DATEADD('WEEK',-2,CURRENT_DATE()))
I have this formula in my column to calculate the start date of a given week :
dateadd(week,[Week]-(1),
dateadd(day,(-1),
dateadd(week,
datediff(week,(0),
CONVERT([varchar](4),[Year],(0))+'-01-01'),
(1))))
Where Week and Year are other fields like 38 and 2012
Problem is, it calculates the start date of week 38/2012 as a monday (17th Sept), I would like it to be a sunday instead (16th Sept) is this possible?
Many thanks.
This will return you the first day of the week, given a week number and a year, assuming that the first day of the week is a Sunday.
Standard exclusions apply, e.g. don't try year 1499.
declare #tbl table ([Week] int, [Year] int)
insert #tbl select 38,2012
union all select 1,2012
union all select 0,2012
union all select 1,2013
select DATEADD(
Week,
[Week]-1,
DATEADD(
Day,
(8-##datefirst)-DATEPART(dw, CAST([Year]*10000+101 AS VARCHAR(8))),
CAST([Year]*10000+101 AS VARCHAR(8))))
from #TBL
Result
2012-09-16 00:00:00.000
2012-01-01 00:00:00.000
2011-12-25 00:00:00.000
2012-12-30 00:00:00.000
Note that the Week number starts from 1, and if the week doesn't start on a Sunday, then the first day of that week could end up in an earlier year (row #4). Because the Weeks are relative, you can use Week 0, -1 etc and it will still give you a result (row #3), rightly or wrongly.
You may also notice I used a different method to create a date out of the year, just as an alternative.
The (8-##datefirst) portion of the query makes it robust regardless of your DATEFIRST setting.
If you want the first day of the week to be Sunday you could change your database to make it so, using the DATEFIRST setting.
function getFirstDateOfThisWeek(d)
{
var TempDate = new Date(d || new Date());
TempDate.setDate(TempDate.getDate() + (#Config.WeekStartOn - 1 - TempDate.getDay() - 7) % 7);
return TempDate;
}
var StartDate = getFirstDateOfThisWeek(new Date()); //1st date of this week