finds the documents which are created 5 years ago - mongodb-query

I have to find documents which are created 5 years ago.
This query is returning everything.
db.col.find({
"createdDate":{
'$gte':new Date(new Date().setYear(new Date().getYear()-5))}
});
I searched around and found it for sql,
select * from table1 where b > YEAR(CURRENT_TIMESTAMP) - 5;
I want something similar in mongo.

You are using incorrect method - getYear()
A number representing the year of the given date, according to local
time, minus 1900.
Returns 113
So new Date().getYear()-5 => 113
new Date(new Date().setYear(113) => 0113-03-16T01:35:13.251Z
Fix:
Use getFullYear() instead.
var dt = new Date();
dt.setYear(dt.getFullYear()-5);
db.col.find({ "createdDate":{'$gte':dt}});

Related

How to get value of form field and past it to another form field

I am developing HR system, I want to calculate how many days off the employee can take.
In the HR table I have three attributes.
1- start_date(when the employee starting to work in the company).
2- leavestaken(how many days off the employee took before).
3- leaves(the number of days available for the employee to take off) which equal to=(months between current date and start_date) * 2.5(beacuse each month give 2.5 days off) - leavestaken
third attribute is automated and not from the user, how I can get the first and second attributive values from field forms, use them in the calculation and save the result in the leaves attribute?
I'm using sql and this only for server side
Server side:
If your start_date is unix timestamp:
if ($model->load(Yii::$app->request->post())) {
n_month = (time() - $model->leaves) / (30 * 24 * 60 * 60);
$model->leaves = ceil(n_month * 2.5) - $model->leavestaken;
# code...
//ceil : Because one day off is not complete, Rounds a number down to the nearest integer
But if it's not unix, you can use the date_diff() method or ...
You can do this in the model file, in the beforeSave or beforeValidate method.
You can use JavaScript to calculate the client side.
My solution was
if ($model->load(Yii::$app->request->post()) ) {
$date = date('m/d/Y');
$datetime1 = date_create($date);
$datetime2 = date_create($model->start_date);
// calculates the difference between DateTime objects
$interval = $datetime2->diff($datetime1);
$n_month= $interval->m + 12*$interval->y;
$model->leaves = ceil($n_month * 2.5) - $model->leavestaken;
$model->save();

LEFT JOIN include data

I have an application which handles school vacation. Unfortunately there are three kinds of different school vacations: Country wide, Federal State wide and City wide vacations. I store all the information in a table days, a table vacation_periods and a connection table slots:
days {
id:integer
date_value:date
}
slots {
id:integer
day_id:integer
vacation_period_id:integer
}
vacation_periods {
id:integer
starts_on:date
ends_on:date
name:string
country_id:integer
federal_state_id:integer
city_id:integer
}
I want to select all days within a specific time frame. Let's say Jan 1st of 2017 to Jan 31st of 2017. I can get those days with:
SELECT * FROM days WHERE date_value >= '2017-01-01' AND
date_value <= '2017-01-31';
But for my vacation calendar I don't just need the days but also the information which vacation_periods are within. Assuming I search for all vacation_periods which are in that time frame and which have
country_id == 1 or federal_state_id == 5 or city_id == 30
I've read about JOINS and LEFT JOINS which seem to be the solution to the problem. But I can't get everything together.
Is it possible to send one SQL request which returns all days within the requested time frame and the additional information if a vacation_period that fits the country_id == 1 or federal_state_id == 5 or city_id == 30 rule is connected via slots to each day. Including the name of that vacation_period?
If one request is not possible: Which is the quickest way to solve this within the database? How many requests? What kind of requests?
If possible I'd like to get a result in some kind of this form:
- date_value: "2017-01-01"
- date_value: "2017-01-02"
- date_value: "2017-01-03"
* vacation_period.id: 15
* vacation_period.name: "foobar"
- date_value: "2017-01-04"
* vacation_period.id: 15
* vacation_period.name: "foobar"
- date_value: "2017-01-05"
* vacation_period.id: 15
* vacation_period.name: "foobar"
- date_value: "2017-01-06"
- date_value: "2017-01-07"
...
The following query might give you the answer you are looking for:
SELECT * FROM days WHERE date_value >= '2017-01-01' AND date_value <='2017-01-31'
INNER JOIN slots ON days.id = slots.day_id
INNER JOIN vacation_periods ON vacation_periods.id = slots.vacation_period_id
I think you can get an unformatted version of what you want (that could be processed into a hierarchical output) with
CREATE TYPE vacation_authority AS ENUM
('COUNTY', 'FED-STATE', 'CITY');
/* not necessary, but cleans up the vacation_period table */
change to let vacation_period have only one id, and a new field authority of type vacation_authority. You can now make a primary key out of either the id field or (id, authority), depending on how the vacation data comes into the system.
SELECT date_value, vp.name, vp.id /* is the ID meaningful or arbitrary? */
FROM dates LEFT JOIN vacation_periods vp
WHERE date_value BETWEEN vp.starts_on AND vp.ends_on; -- inclusive range
Now if there are multiple holidays spanning a given date, this will be multiple records in the output. It's not clear what you want in this case.
None of the other answers was able to solve my problem but they let me to the solution so I'm grateful for them. Here's the solution:
SELECT days.date_value, slots.period_id, vacation_periods.name FROM days
LEFT OUTER JOIN slots ON (days.id = slots.day_id)
LEFT OUTER JOIN vacation_periods ON (slots.period_id = vacation_periods.id)
WHERE days.date_value >= '2017-01-05'
AND days.date_value <='2017-01-15'
AND (vacation_periods.id IS NULL
OR vacation_periods.country_id = 1
OR vacation_periods.federal_state_id = 5)
ORDER BY days.date_value;

Kettle Datedif month issue

I need to reproduce the kettle Datedif function in the R programming language. I need the 'datedif month' option. I thought reproducing would be pretty easy but I have some 'weird behaviour' in pentaho. As an example:
ID date_1 date_2 monthly_difference_kettle daydiff_mysql
15943 31/12/2013 28/07/2014 7 209
15943 31/12/2011 27/07/2012 6 209
So in pentaho kettle I used the formula-step and the function DATEDIF(date2,date1,"m"). As you can see when I calculate the daily difference in mysql I get for both records the same amount of days in difference (209), however, when the monthly difference is calculated via the formula step in pentaho kettle I get a different result in months (7 and 6 respectively). I don't understand how this is calculated...
Can anyone produce the source code for the 'DATEDIF months' function in pentaho? I would like to reproduce it in R so I get exactly the same results.
Thanks in advance,
best regards,
Not sure about mysql, but i think it is the same. In PostgreSQL date difference gives integer value (in days). It means both rows has total match in days.
Calculating month difference non trivial. What is month (28, 30, 31 day)? Shall we count if month is not full?
Documentation states If there is not a complete month between the dates, 0 will be returned
But according to source code easy to understand how calculated datedif:
Source code available via github https://github.com/pentaho/pentaho-reporting/blob/f7defbcfc0e8f48ad2b139fe9820445f052e0e78/libraries/libformula/src/main/java/org/pentaho/reporting/libraries/formula/function/datetime/DateDifFunction.java
private int addFieldLoop( final GregorianCalendar c, final GregorianCalendar target, final int field ) {
c.set( Calendar.MILLISECOND, 0 );
c.set( Calendar.SECOND, 0 );
c.set( Calendar.MINUTE, 0 );
c.set( Calendar.HOUR_OF_DAY, 0 );
target.set( Calendar.MILLISECOND, 0 );
target.set( Calendar.SECOND, 0 );
target.set( Calendar.MINUTE, 0 );
target.set( Calendar.HOUR_OF_DAY, 0 );
if ( c.getTimeInMillis() == target.getTimeInMillis() ) {
return 0;
}
int count = 0;
while ( true ) {
c.add( field, 1 );
if ( c.getTimeInMillis() > target.getTimeInMillis() ) {
return count;
}
count += 1;
}
}
Append 1 month to start date till it will become bigger then end date

How to join every row from one table, with the latest dated row from another table, using LINQ2SQL

Let's say I've got a table called [Items] which has a primary key ItemID, and I've got a table called [ItemStatuses] which is linked with the ItemID, has a Auto-Increment ID and has a Date (and other columns to capture various things)
Which means, for every Item, I'll have many ItemStatuses.
Items:
ItemID
1
2
ItemStatuses:
ID ItemID Date
----------------------------
1 1 1/1/2010...
2 1 1/2/2010...
3 1 1/3/2010...
4 2 1/1/2010...
5 2 1/2/2010...
I want to be able to join each Item with the latest ItemStatus. I've got a solution which grabs the information into entity objects and then does the work, but this takes so much time. If I could query this using LINQ2SQL it would be so much faster. I've read several other questions on stackoverflow but none of the examples make sense for my scenario. I've tried to figure this out, but still cannot get it to work.
I need this:
ItemID Date
-----------------------
1 1/3/2010...
2 1/2/2010...
This is a simplistic example. I don't want just specific columns. There are MANY columns in the Items and ItemStatuses that I need to capture. But the ones mentioned are the control columns.
If someone could give me a hand I would really appreciate it.
The query I have now doesn't work, but it's where I'm at right now:
var results = from i in context.Items
from s in context.ItemStatuses
where s.ItemID.Equals(i.ItemID) s.Date <= inputDate
orderby s.Date descending
select new { i, s };
The Following query joins the two tables and selects only the ItemStatuses that has the latest Date value:
var results = from i in context.Items
join s in context.ItemStatuses
on
new
{
ID = i.ItemID,
maxDate = (
from ss in context.ItemStatuses
where ss.Date <= inputDate
select ss.Date
).max
}
equals new
{
ID = s.ItemID,
maxDate = s.Date
}
select new
{
i.ItemID, s.Date
};

Convert SQL to NHibernate HQL

I should convert to the fallowing SQL-Query to NHibernate HQL (NHibernate 3.2). But I don't know, how I have to translate the FLOOR, DATEDIFF and GETDATE.
SELECT Birthday FROM Person
WHERE 1 = (FLOOR(DATEDIFF(dd,Birthday,GETDATE()+10) / 365.25))
-
(FLOOR(DATEDIFF(dd,Birthday,GETDATE()-5) / 365.25))
Something to get started with.
Select Birthdays where Birthday between now-5 days and now+10 days.
var today = DateTime.Now();
var results = session.CreateQuery("select p.Birthday from Person
where p.Birthday>= :from and p.Birthday<=:to")
.SetParameter("from", today.AddDays(10))
.SetParameter("to", today.Subtract(new TimeSpan(5, 0, 0, 0)))
.List<DateTime>();
Although I think you want to get birthdays regardless of the year.
In order to replicate this query in HQL you are going to have to register the specific SQL functions you need using this technique:
Register Custom SQL Function in NHibernate
Then you should be able to replicate your SQL query in HQL.
This is a good question on the SQL side of things:
SQL Select Upcoming Birthdays
Fresh tactics:
Register the SQL Function for the datediff:
RegisterFunction("datediffdays",
new SQLFunctionTemplate(NHibernateUtil.Int32, "datediff(dd,?1, ?2)"));
HQL Query
var result = session.CreateQuery(#"from Person
where 1 = (floor(datediffdays(Birthday,current_timestamp()+10) / 365.25))
- (datediffdays(Birthday,current_timestamp()-5) / 365.25))")
.List<Person>();
Untested, but would something like:
var dateStart = DateTime.Now.AddDays(-5).Ticks/365.25D;
var dateEnd = DateTime.Now.AddDays(10).Ticks/365.25D;
session.QueryOver<Person>()
.WhereRestrictionOn(x => x.Birthday.Ticks/365.25D)
.IsBetween(dateStart).And(dateEnd)
.List();
This do the same thing?
Taking a look at the source code, floor is already registered in the dialect, so the following:
var result =
session.CreateQuery(#"from Person
where 1 = (FLOOR(DATEDIFF(dd,Birthday,GETDATE()+10) / 365.25))
-
(FLOOR(DATEDIFF(dd,Birthday,GETDATE()-5) / 365.25))")
.List<Person>();
Produces the following SQL:
select person0_.Id as Id2_,
person0_.Birthday as Birthday2_
from [Person] person0_
where 1 = floor(DATEDIFF(dd,
person0_.Birthday,
GETDATE()
+ 10)
/ 365.25)
- floor(DATEDIFF(dd,
person0_.Birthday,
GETDATE()
- 5)
/ 365.25)