I have a date field in a hive table following this format:
'YYYY-MM-DD'
I'm looking for a function (let's call this yet-to-be-discovered-by-me function dayofweek()) that will return 'friday' when run on today's date. So, to be explicitly clear, this query:
SELECT DAYOFWEEK(DT.ds), DT.ds
FROM dateTable DT
WHERE DT.ds = '2014-11-14'
LIMIT 1
would return this value:
'friday' '2014-11-14'
Any help would be greatly appreciated :) google searching as of yet unfruitful.
Clark
P.S. The response to this question did not work for me...error returned: 'Invalid function 'dayofweek''
Should you care for an equation, following is C code hopefully simple enough to translate into SQL.
Important to use integer math.
#define MARCH 3
int dow_Sunday0(int year, int month, int day) {
if (month < MARCH) {
month += 12;
year--;
}
// Add days for each year and leap years
day += year + year/4 - year/100 + year/400;
// add days for the month
day += month*30 + ((month-MARCH)*39 + 25)/64;
// modulo 7
return (day+3)%7;
}
This works for valid Gregorian calendar dates.
Use DAYNAME() function, like this:
mysql> select dayname('2014-11-14');
+-----------------------+
| dayname('2014-11-14') |
+-----------------------+
| Friday |
+-----------------------+
1 row in set (0.00 sec)
So, your query will become:
SELECT DAYNAME(DT.ds), DT.ds
FROM dateTable DT
WHERE DT.ds = '2014-11-14'
LIMIT 1
Related
I want to create an SQL statement that looks for the last 2 months.
For example:
Select *
from x
where sampledate<= YYYYMM-2
currently i am using this:
(year(from_unixtime(unix_timestamp()))*100+month(from_unixtime(unix_timestamp())))-1
but it returns wrong statements for the first 2 months of a year :(
My idea is to calculate with a date and then change it to a yyyymm integer format.
Any ideas?
Could you try this:
SELECT colomn
FROM table
WHERE date > (SELECT add_months(from_unixtime(unix_timestamp()),-2));
or you can use:
SELECT colomn
FROM table
WHERE date > to_date(SELECT year(add_months(from_unixtime(unix_timestamp()),-2))+month(add_months(from_unixtime(unix_timestamp()),-2)));
Combined with regex&substring:
SELECT colomn
FROM table
where sampledate>=substr(regexp_replace(add_months(from_unixtime(unix_timestamp()),-2), '-',''),1,6)
to get a YYYYMM date
If you want to avoid converting an integer, in YYYYMM format, to and from a date, you can just use maths and CASE statements...
For example YYYYMM % 100 will give you MM. Then you can check if it's 2 or less. If it is 2 or less, deduct 100 to reduce by a year, and add 12 to get the month as 13 or 14. Then, deducting 2 will give you the right answer.
Re-arranging that, you get YYYYMM - 2 + (88, if the month is 1 or 2)
sampledate <= YYYYMM - 2 + CASE WHEN YYYYMM % 100 <= 2 THEN 88 ELSE 0 END
The better idea may just be to reshape your data so that you actually have a (real) date field, and just use ADD_MONTHS(aRealDate, -2)...
EDIT:
If your actual issue is generating the YYYYMM value for "two months ago", then deduct the 2 months before you use the YEAR() and MONTH() functions.
year( ADD_MONTHS(from_unixtime(unix_timestamp()), -2) )*100
+
month( ADD_MONTHS(from_unixtime(unix_timestamp()), -2) )
Try something like this.
First, a utility to get the date n months in the future/past:
public Date nMonthsFromDate(Date date, int interval) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// E.G. to get 2 months ago, add -2
cal.add(Calendar.MONTH, interval);
Date result = cal.getTime();
return result;
}
Criteria query on the entity, here Member:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> q = cb.createQuery(Member.class);
Root<Member> memberRoot = q.from(Member.class);
Date theDate = nMonthsFromToday(-2);
Predicate pred = cb.greaterThanOrEqualTo(
memberRoot.<Date>get("timeStamp"), theDate);
q.where(pred);
TypedQuery<Member> theQuery = em.createQuery(q);
String qStr = theQuery
.unwrap(org.apache.openjpa.persistence.QueryImpl.class)
.getQueryString();
LOG.info("Query: " + qStr);
List<Member> results = null;
try {
results = theQuery.getResultList();
} catch (Exception e) {
LOG.severe(e.getMessage());
e.printStackTrace();
}
return results;
Finally, beware of comparing a date [java.util.Date] to a timestamp [util.sql.Date]. Due to a quirk in Java, for equivalent dates, date.equals(timeStamp) returns true, BUT timeStamp.equals(date) returns FALSE. To conform both dates to a java.util.Date:
public java.util.Date getStandardDate(Date date) {
return new java.util.Date(date.getTime());
I need some help to understand a certain line in a code. The code takes the turnovers of every Monday in the year 2010 and at the last line in summarizes all the turnovers to one.
Here is the code:
SELECT
CASE
WHEN GROUPING (DATUM) = 1 THEN 'Gesamtumsatz'
ELSE CAST (DATUM AS VARCHAR (40))
END AS MONTAGSDATEN,
AVG (VERKAUFSWERT * VERKAUFSMENGE) as UMSATZ
FROM Data_Star_Awesome.dbo.VERKAUFSFAKTEN vk
INNER JOIN DIMDATUM dimD on vk.DATUMID=dimD.DATUMID
WHERE DATEDIFF(dd,0, DATUM)%7=0
AND JAHR = 2010
GROUP BY ROLLUP (DATUM)
The problematic line I don't understand is the following:
WHERE DATEDIFF(dd,0, DATUM)%7=0
What I know is that it takes the days out of the date variable but I don't get the %7=0 part. The DATEDIFF function should give back all the days. Are these days saved in the % the placeholder? And how does it get all the Mondays by using the 7=0?
It would be great if someone could help me out.
Thanks a lot :)
Modulo or % operator is the same as in a lot of programming languages. It returns the remainder after the division.
The DATEDIFF function takes two dates and returns the difference in a specified datepart, which in your query is the days represented by dd.
Also 0 as date converts to 1/1/1900 which happens to be a Monday. So your query is calculating the days between 1/1/1900 and the DATUM field in days and if its Mod is 0 then DATUM is Monday.
You could simply say:
datename(weekday,<datetime-value>)
Which will return 'Monday', 'Tuesday', 'Wednesday', etc. The problem with this approach is that the returned value is localized. If the SQL server's language is changed, your test for 'Monday' will fail.
This expression will always work:
( ##datefirst + ( datepart(weekday,today) - 1 ) ) % 7
It evaluates to 1-7, where Monday is always 1 and Sunday is always 7, regardless of culture/language settings or the current value of ##datefirst, as set by set datefirst.
We can then convert this into this discriminant function, yielding 1 or 0 to indicate whether or not the date is Monday:
case ( ##datefirst + ( datepart(weekday,today) - 1 ) ) % 7 when 1 then 1 else 0 end
I have salesdate for whole last year (01/01/2012 to 12/31/2012). I want to create
a week variable in such a way that there are only 4 weeks consistent over the months.
In other words, I want
01/01/2012-01/07/2012 = week1
01/08/2012-01/14/2012 = week2
01/15/2012-01/21/2012 = week3
01/22/2012-01/31/2012 = week4
(I can not use ww. format because my week 4 does not fit the always definition of week 4 in Oracle SQL Developer.)
I am wondering if anybody can help me on this.
Try this expression:
select LEAST(TRUNC((EXTRACT(day FROM salesdate) + 6) / 7), 4) week
FROM salesdata;
Note:
EXTRACT extracts the day from the date
TRUNC( (x + 6) / 7) divides it by seven days and truncates it to an integer number
LEAST( x, 4 ) limits it to a maximum of 4
Well your last week has 9 days, so that is kind of weird...
but you could try something like:
CREATE OR REPLACE FUNCTION GET_WEIRD_WEEK(I_DATE DATE)
RETURN NUMBER AS
BEGIN
RETURN CASE
WHEN FLOOR(TO_CHAR(I_DATE,'DD')/7)+1 > 3
THEN 4
ELSE FLOOR(TO_CHAR(I_DATE,'DD')/7)+1
END;
END;
otherwise i would suggest you distribute the days evenly across the month's quarters:
CREATE OR REPLACE FUNCTION GET_WEIRD_WEEK(I_DATE DATE) RETURN NUMBER AS
BEGIN
RETURN FLOOR(TO_CHAR(I_DATE,'DD')/TO_CHAR(LAST_DAY(I_DATE),'DD')*4)+1;
END;
I am trying to retrieve the month value of a calculation :
SELECT strftime('%m', 'now') - strftime('%m', e.date) AS something FROM ...
But here are the results I get and what I really want :
NOW - 2012-02-03 = 0 // want 11
NOW - 2012-11-02 = -9 // want 3
NOW - 2012-02-02 = 0 // want 12
NOW - 2012-01-02 = 1 // want 13
As I can see I can almost get the right values by doing sqlResult + 12 (except for first example) but is there a way to achieve this directly in the SQL statement and to get exact values in every case ?
EDIT : Finally here is the solution
SELECT CAST ((julianday('now') - julianday(e.date_retour)) / 30 AS integer) AS something
You need to take the year into account. You can do this as:
select strftime('%Y', 'now')*12+strftime('%m', 'now') -
(strftime('%Y', e.date)*12+strftime('%m', e.date))
The month returns the month of the year. So, it is no surprise that something like 2 (February) - 9 (September) produces a negative number.
To handle day of month, I think you have to handle the date arithmetic yourself:
select (strftime('%Y', 'now')*12+strftime('%m', 'now') -
(strftime('%Y', e.date)*12+strftime('%m', e.date))
) -
(case when strftime('%d', 'now') < strftime('%d', e.date) then 0 else 1 end)
SQLite has the ability to add months to a date. Unfortunately, it doesn't seem to have the ability to take the difference in months between dates.
You are not really looking at difference between two months but, considering their years as well.
So you need to do like this:
SQLite (SQL.js) Demo
SELECT round((julianday(Date('now')) -
julianday(Dates))/30) as MonthsDiff
from demo;
| MonthsDiff |
--------------
| 11.0 |
| 2.0 |
you are getting the weird numbers because you are asking the strftime function to return only the month and then you are subtracting only the months...
How about you do this?
SELECT strftime('%s', date()) - strftime('%s', '2012-03-03') as blah
this will subtract the unix timestamps and then you can convert it back to readable months or whatever...
or this could give you number of days...
SELECT julianday(date()) - julianday('2012-03-03') as blah
I need to calculate the weeks out from a date in my MySQL select statement. There is a date column in one of the tables, and I need to calculate how many weeks away the date is.
SELECT EventDate, (calculation) AS WeeksOut FROM Events;
Example:
6 days away, weeks out = 0
7 days away, weeks out = 1
13 days away, weeks out = 1
14 days away, weeks out = 2
Use the DATEDIFF function:
ROUND(DATEDIFF(end_date, start_date)/7, 0) AS weeksout
The problem with WEEKS is that it won't return correct results for dates that cross over January 1st.
The 0 is the number of decimal places to use in the ROUND function.
In order to get past the whole "New Year" issue and you still want to use WEEK(), I found the following method quite effective.
SELECT
YEAR(end_date)*52+WEEK(end_date)
- YEAR(start_date)*52 - WEEK(start_date) as weeks_out
FROM
events;
The difference with this method (as opposed to the DATEDIFF method) is that it is aligned with the week. So today (which is Monday) and last Friday would return 1 using this method, but would return 0 with the DATEDIFF method
Here's a simple way to do it:
SELECT EventDate, (week(EventDate) - week(curdate())) AS WeeksOut FROM Events;
Example:
mysql> select week('2010-11-18') - week ('2010-10-18');
+------------------------------------------+
| week('2010-11-18') - week ('2010-10-18') |
+------------------------------------------+
| 4 |
+------------------------------------------+
1 row in set (0.00 sec)
Another option is calculate the interval in days and divide by 7:
SELECT EventDate, datediff(EventDate,curdate())/7 AS WeeksOut FROM Events;
Example:
mysql> select datediff('2010-11-18' , '2010-10-18') / 7;
+-------------------------------------------+
| datediff('2010-11-18' , '2010-10-18') / 7 |
+-------------------------------------------+
| 4.4286 |
+-------------------------------------------+
1 row in set (0.00 sec)
In newer versions of MYSQL if you use the timestamp as column type, you can use TIMESTAMPDIFF:
SELECT TIMESTAMPDIFF(WEEK, '2020-06-09 08:59:36', '2020-09-09 08:58:25');
|-----------------------------------------------------------------------|
| 13 |
So in your example it would be:
SELECT TIMESTAMPDIFF(WEEK, NOW(), EventDate) AS WeeksOut FROM Events;
Try TIMESTAMPDIFF
TIMESTAMPDIFF(WEEK, curdate(), EventDate) AS WEEKS_DIFFERENCE