I have this model :
public class Post {
private Long expiryDate; // A timestamp
}
And repository as :
#Repository
public interface PostRepository extends JpaRepository<Post, Long> {
Page<Post> findAllByOrderByExpiryDateDesc(Pageable pageable);
}
What I want to do:
When the expiry date has passed (post expired, current date greater than expiry date) => orderBy desc
Else, When the expiry date not yet passed (post not expired) => orderBy asc
Example: if I have the expiry date list: Monday, Tuesday, Wednesday, Thursday and Friday
and that today is Wednesday (Wednesday not yet expired).
Wanted result:
Wednesday
Thursday
Friday
Tuesday
Monday
Someone got any solution please?
You could try the following query:
SELECT p FROM Post p
ORDER BY CASE
WHEN p.expiryDate > CURRENT_TIMESTAMP THEN p.expiryDate
ELSE -p.expiryDate
END ASC
(you might need some casting to make it work, but since you didn't mention the RDBMS you're using, you'll need to check it out yourself)
I found the solution (with the help of #crizzis),
This Query work perfectly :
#Query(value = "from Post as p ORDER BY " +
"CASE WHEN p. expiryDate > :currentTime THEN -p.expiryDate ELSE null END desc," +
"CASE WHEN p. expiryDate < :currentTime THEN -p.expiryDate ELSE null END asc")
Page<Post> findAll(Long currentTime, Pageable pageable);
For native query (h2 database example)
SELECT * FROM Post p
ORDER BY
CASE WHEN p.expiryDate > currentTime THEN -p.expiryDate END desc,
CASE WHEN p.expiryDate < currentTime THEN -p.expiryDate END asc;
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 dont know about other countries but in South Africa we have a public holiday on a Monday if the Sunday was a Public holiday. I need to write an Update statement that will return the date after x number of days and should the date be a monday after a public holiday it should add an additional day. My simple update statement looks like:
UPDATE tbl_ProjectTracker
set Predicted_Date = DATEADD(DAY, 20, Actual_Eng_Start_date)
I already have a table for referencing but I am not sure if I should determine the additional day on the table or on the Update statement.
Please assist
You should have a PublicHoliday table
Then you could Update predicted_date like that
DECLARE #PublicHoliday AS TABLE
(
HolidayDate date
)
DECLARE #NumberDaysPredict int = 20
UPDATE pt
set pt.Predicted_Date = DATEADD(DAY, #NumberDaysPredict + hl.NumberHolidaysOnSunday, pt.Actual_Eng_Start_date)
FROM tbl_ProjectTracker pt
CROSS APPLY
(
SELECT Count(*) AS NumberHolidaysOnSunday
FROM #PublicHoliday ph
WHERE ph.HolidayDate BETWEEN pt.Actual_Eng_Start_date AND DATEADD(DAY, #NumberDaysPredict, Actual_Eng_Start_date)
AND Datepart(dw,ph.HolidayDate) = 1 -- Sunday
) hl
A simple way would be a case construct for the number of days:
UPDATE tbl_ProjectTracker
set Predicted_Date = DATEADD(
DAY,
CASE WHEN Actual_Eng_Start_date IN
(select day from public_holidays where datepart(dw, day) = 1) THEN 21 ELSE 20 END,
Actual_Eng_Start_date)
Unfortunately SQL Server's date / time functions are weak to say the least. The result of DATEPART(dw, ...) depends on a setting (DATEFIRST), so the query is kind of unreliable. Always make sure the setting is correct when you run it. It has been requested to extend DATEPART such as to accept an optional parameter for DATEFIRST so you'd get a consistent query, but Microsoft has closed this as "unsolvable" (https://connect.microsoft.com/SQLServer/feedbackdetail/view/432303/datepart-dw-date-should-allow-optional-date-first-Parameter).
In my where clause I have to manually change the weeks for both the clauses ("Week" and "Can_Week_End"). And in my example, the weeks end on Sundays (12/4,12/11,12/18, etc...). How can I manipulate the where clause filter so it does the date changing automatically. If someone queries out
select * from myview
Monday morning, it will show the data correspondent to the last week ending on the passed Sunday (day before). Is there a way to accomplish this? Please provide insights.
create view myview
as
select case when sd."Build_Spec" = 'Spec' then 'X' else '' end as "Spec",
case when sd."Build_Spec" = 'Build' then 'X' else '' end as "Build",
Case when sd."Can_Week_End" = '' then '' else 'X' end as "Cancel",
sd."Price",
sd."Sq_Ft" as "SF",
sd."Price"::money / to_number(sd."Sq_Ft",'99999999') as "PPSF",
case when sd."Realtor_Sale" is not null then 'X' else '' end as "Realtor"
from datapcr sd
left join comppcr ad on "Address" = "Address_of_New_Home"
where sd."Week" = '2016-12-18'or sd."Can_Week_End" = '12/18/2016'
order by "Cancel"
It's unclear why you have two different date formats in the same query, and it's also unclear where you want to draw the line exactly. but basically, you can solve this with date_trunc():
...
where sd."Week" = date_trunc('week', now())::date - 1
...
date_trunc('week', now()) returns Mon, 00:00 of the current week. Cast to date and subtract 1 to get the date of last Sunday. Voilá.
Related:
How do I determine the last day of the previous month using PostgreSQL?
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
I would like a certain schedule rule (with notifications) to be executed only during work days. I.e. I would like to avoid receiving notifications on Saturdays and Sundays. How can I check for a current day of the week in YouTrack Workflow?
Using format you can get day of week abbreviation or full name.
var dayOfWeekAbr = now.format(#E);
var dayOfWeek = now.format(#EEEE);
Or using year-month-day literal (2014-01-05 was Sunday):
var day = (created - 2014-01-05).millis / 86400000 % 7;
if (day > 1 && day < 6) {
message("Work day");
}
There isn't built-in YouTrack workflow mechanism of defining a current day of week, but the simple workaround allows to do it:
schedule rule day of week
daily at 10:00:00 [for all issues] {
var monday = {issue: A-1}.created - 1 day;
while (i < 50) {
if (monday + (i * 7) days < now && now < monday + (i * 7 + 5) days) {
//now is the work day
}
}
The issue A-1 is a sample issue created on Tuesday, so {issue: A-1}.created - 1 day refers to the Monday.
The while cycle finds the current week and if() defines whether today is a work day or a weekend.
I faced the same issue, I didn't find the previous solutions readable.
The solution I've implemented:
var today = now.format(utc).substring(0, 3);
if (today == "Mon" || today == "Tue" || today == "Wed" || today == "Thu" || today == "Fri") {
message("Work day!");
}
Probably the shortest solution specifically for avoiding weekends, as Saturday and Sunday are the only days beginning with an uppercase 'S':
if(!now.format(#E).startsWith("S", opts)) {}
/e: as Artem correctly pointed out, this may have to be adopted or does not work for certain localizations - it does at least for German and English.