MySql query with dates in NodeJs - mysql

i have a table in MySQL database of people, with their Birthrates.
for example '1991-11-21'
I have two values, one is minimum age(like 22), and the other is maximum age(like 33).
I would like to make a query that gets me all the records with people between the minimum age value, and the maximum.
I am working with NodeJs.
any ideas?

One solution is to do all the work in MySQL and inject your variables into your MySQL statement
To do that you will need a combination of these answers
1) Get the date from x years ago
Selecting all records from one year ago till now
2) Select results between date range
Select mysql query between date?
You should end up with a query something like this:
select *
from *table_name*
where *datetime_column*
between DATE_SUB(NOW(),INTERVAL 22 YEAR)
and DATE_SUB(NOW(),INTERVAL 33 YEAR);
Note: you may need to add a year to the second date (33+1) to get the full range of someones age being 33 (you are 33 until the day you turn 34)
Or if you prefer you can calculate your dates in JS, but depending how you do it you may need to format your dates so they will work in your query

Try this :
SELECT age, birthday FROM tablename WHERE age > 22 AND age < 33
I took this in wrong way :
i think here is correct :
SELECT *, TIMESTAMPDIFF(YEAR,birthday,CURDATE()) as age FROM student WHERE TIMESTAMPDIFF(YEAR,created,CURDATE()) > 22 AND TIMESTAMPDIFF(YEAR,birthday,CURDATE()) < 33

Related

count method returns different values depending on date in condition

I'm running a query that looks at the number of days where an activity for a record exists over the last three days (today included) in the database using the GroupBy gem to group them by day. Here is the full query:
Record.activities.where("created_at >= ?", 2.days.ago.beginning_of_day.in_time_zone).group_by_day(:created_at).count.count
2 days ago, I have 1 activity, yesterday I have 0 and today I have 2. This should return 2 (not 3, it's counting the days not the activities) but for some reason it returns 3. What's even stranger is that if I change 2.days.ago to 1.day.ago or 0.days.ago, it returns the correct value, 1. It ignores yesterday where there were no activities and only counts the day (today) where it recognised there was an activity.
If I remove the second .count, here's what it returns for 2.days.ago...
{Tue, 21 Nov 2017=>1, Wed, 22 Nov 2017=>0, Thu, 23 Nov 2017=>2}
and if I run it for 1.day.ago, I get...
{Thu, 23 Nov 2017=>2}
Here is the raw SQL for the 2.days.ago query..
SELECT COUNT(*) AS count_all, strftime('%Y-%m-%d 00:00:00 UTC', created_at)
AS strftime_y_m_d_00_00_00_utc_created_at
FROM "activities"
WHERE "activities"."goal_id" = ? AND (created_at >= '2017-11-21 00:00:00')
AND (created_at IS NOT NULL)
GROUP BY strftime('%Y-%m-%d 00:00:00 UTC', created_at)
After some more testing, I noticed it only ignores a day with 0 activities if the x in x.days.ago falls on the day with 0. If there is more than 1 day with 0 activities, it will ignore the first one as it should but then count the other days with 0 that come after...
Not sure what I'm missing here but would appreciate any help finding the issue.
Let me know if you need any more information.
You can use .having('count(activities.id) > 0') to ignore days with no activity
untested query below:
Record.activities
.select('count(activities.id) as count_all,date(activities.created_at) as day')
.where("created_at >= ?", 2.days.ago.beginning_of_day.in_time_zone)
.group('day').having('count_all > 0')
First of all your solution is not ok, because you need to make it in sql query (while you load all the data to ruby object and then sort them. It will be a bottle neck during scale). Just put the same thing to sql. I think this one should work:
Record.activities.where("created_at >= ? AND count_all > 0", 2.days.ago.beginning_of_day.in_time_zone).group_by_day(:created_at).count
Then about why you get 3 when you expect to get 2. Sql COUNT(*) returns number of rows. In your case you will always have 3 unique days, so 3 unique rows (group_by group them by their uniqueness). You must filter days with 0 count as I made in my query to filter rows, that have 0 in count, but still get counted
I've found a way to return the right result but still curious to know why that initial query returns those results.
Here is the query that works:
Record.activities.where("created_at >= ?", 4.days.ago.beginning_of_day.in_time_zone).group_by_day(:created_at).count.reject {|k,v| v == 0 }.count

Select leave data from attendance table given the following condition

I have attendance data for employees stored in the table attendance with the following column names:
emp_id (employee ID)
date
type (leave, absent, etc.)
(there are others but I'm omitting them for the sake of simplicity)
My objective is to retrieve all dates of the given month on which the employee was on leave (type = 'Leave') and the last leave taken in the last month, if any.
It's easy to do it using two queries (I'm using PHP to get process the data), but is there any way this can be done in a single query?
I'm answering my own question so as to close it. As #bpgergo pointed out in the comments, UNION will do the trick here.
SELECT * FROM table_name
WHERE type="Leave" AND
date <= (CURRENT_DATE() - 30)
Select the fields, etc you want then se a combined where clause using mysql's CURRENT_DATE() function. I subtracted 30 for 30 days in a month.
If date is a date column, this will return everyone who left 1 month or longer ago.
Edit:
If you want a specific date, change the 2nd month like this:
date <= (date_number - 30)

MySQL Date in where clause

I have a table which contains date (Field Type: Date and Date Format: %Y-%m-%d) as a field. I need to select all the rows from the table for all the years whose date is not between Dec 3rd and Dec 24th.
The table contains month and day as a separate fields.
The result can be obtained by using the following query:
select * from mytable where date not in (select date from mytable where month=12 and day between 3 and 24);
But i m trying to get the result in a single query like the below one but it gave empty rows:
select * from mytable where date not between '%Y-12-03' and '%Y-12-24';
Can it be done in a single query like the above one?
SELECT *
FROM mytable
WHERE MONTH(`date`) <> 12
OR DAY(`date`) NOT BETWEEN 3 AND 24
;
This will give you every row that meets the requirements. I'm sure someone has a faster way of doing this, since this will ignore all indexes and will likely be slow on a large dataset, but it does work and return the data you require, so if no-one can suggest an improvement this will answer your question.

Mysql maximum rows in a variable timeframe

I'm making a fitness logbook where indoor rowers can log there results.
To make it interesting and motivating I'm implementing an achievement system.
I like to have an achievement that if someone rows more than 90 times within 24 weeks they get that achievement.
Does anybody have some hints in how i can implement this in MYSQL.
The mysql-table for the logbook is pretty straightforward: id, userid, date (timestamp),etc (rest is omitted because it doesn't really matter)
The jist is that the first rowdate and the last one can't exceed the 24 weeks.
I assume from your application that you want the most recent 24 weeks.
In mysql, you do this as:
select lb.userid
from logbook lb
where datediff(now(), lb.date) >= 7*24
group by userid
having count(*) >= 90
If you need it for an arbitrary 24-week period, can you modify the question?
Just do a sql query to count the number of rows a user has between now and 24 weeks ago. This is a pretty straight forward query to run.
Look at using something with datediff in mysql to get the difference between now and 24 weeks ago.
After you have a script set up to do this, set up a cron job to run either every day or every week and do some automation on this.
I think you should create a table achievers which you populate with the achievers of each day.
You can set a recurrent(daily, right before midnight) event in which you run a query like this:
delete from achievers;
insert into achievers (
select userid
from logbook
where date < currenttimestamp and date > currenttimestamp - 24weeks
group by userid
having count(*) >= 90
)
For events in mysql: http://dev.mysql.com/doc/refman/5.1/en/events-overview.html
This query will give you the list of users total activity in 24 weeks
select * from table groupby userid where `date` BETWEEN DATE_SUB( CURDATE( ) ,INTERVAL 168 DAY ) AND CURDATE( ) having count(id) >= 90

Why doesn't BETWEEN work in this MySQL query?

Query 1 works but query 2 doesn't:
Query #1:
SELECT * FROM `users` WHERE users.dob <= '1994-1-14' AND users.dob >= '1993-1-14' LIMIT 10
Query #2:
SELECT * FROM `users` WHERE users.dob BETWEEN '1994-1-14' AND '1993-1-14' LIMIT 10
The 2nd one should be able to do the same thing as the first but I don't understand why it's not working.
The dob (date of birth) field in the users table is a type date field with records that look like this:
1988-11-08
1967-11-14
1991-03-09
1958-03-08
1967-06-30
1988-10-19
1986-01-23
1965-09-20
YEAR - MONTH - DAY
With either query #1 or #2 I'm trying to get back all users who are between 18 and 19 years of age, because 1994-1-14 is exactly 18 years from today and 1993-1-14 is 19 years from today. So is there a way to get the between query to work?
By not working I mean it doesn't return any records from the db while the working query does.
Also is the between query more efficient or is the performance difference negligible?
To answer the first part: "expr BETWEEN min AND max". Try switching those 2 dates in the second query.
The usage is wrong. See the BETWEEN documentation:
expr BETWEEN min AND max is equivalent to (min <= expr AND expr <= max).
Therefore, users.dob BETWEEN '1994-1-14' AND '1993-1-14' is the same as ('1994-1-14' <= users.dob AND users.dob <= '1993-1-14'), of which there will never be more than 0 results.
Simply reverse the order :)
There will be no performance difference when using either form, possibly subject to the note below. This transformation happens at the query planner level. However, if you have concerns, remember to profile, profile, profile. Then you can see for yourself and appease the premature-optimization demons.
Also note the ... note:
For best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type.