I have a table with people and their birth dates. I want to SELECT them ordered by the "number of days until next birthday".
I have tried with the DAYOFYEAR() function:
SELECT id, DAYOFYEAR(datebirth)-DAYOFYEAR(NOW()) AS daystobd
FROM users ORDER BY daystobd;
But... I got negative daystobd if the birthday has passed this year. The intention is to have those listed at the end.
Any idea ?
EDIT: daystobd should reflect the real number of days until next birthday
NEW EDIT:
I managed to do it with UNION, but I think surely there is a more "elegant" way to do this.
SELECT id, DAYOFYEAR(datebirth)-DAYOFYEAR(CURDATE()) AS daystobd
FROM users WHERE DAYOFYEAR(datebirth)-DAYOFYEAR(CURDATE())>=0
UNION
SELECT id, 365+DAYOFYEAR(datebirth)-DAYOFYEAR(CURDATE()) AS daystobd
FROM users WHERE DAYOFYEAR(datebirth)-DAYOFYEAR(CURDATE())<0 ORDER BY daystobd
Compare MMDD of today and the user's birthday. Then build the next birthday accordingly with the current or next year.
SELECT
id,
next_birthday,
DATEDIFF(next_birthday, NOW()) AS daystobd
FROM
(
SELECT
id,
datebirth,
CASE WHEN DATE_FORMAT(datebirth, '%m%d') >= DATE_FORMAT(NOW(), '%m%d')
THEN CONCAT(EXTRACT(YEAR FROM NOW()), '-', DATE_FORMAT(datebirth, '%m-%d'))
ELSE CONCAT(EXTRACT(YEAR FROM NOW()) + 1, '-', DATE_FORMAT(datebirth, '%m-%d'))
END AS next_birthday
FROM users
) data
ORDER BY DATEDIFF(next_birthday, NOW());
Give them a weight if below 0
ORDER BY CASE WHEN datstobd<0 THEN 1 ELSE 0 END,daystobd
Related
RDBMS: MySQL
The time column(s) datatype is of datetime
For every hour of the 24 hour day I need to retrieve the number of rows in which their start_time matches the hour OR the end_time is great than or equal to the hour.
Below is the current query I have which returns the data I need but only based off of one hour. I can loop through and do 24 separate queries for each hour of the day but I would love to have this in one query.
SELECT COUNT(*) as total_online
FROM broadcasts
WHERE DATE(start_time) = '2018-01-01' AND (HOUR(start_time) = '0' OR
HOUR(end_time) >= '0')
Is there a better way of querying the data I need? Perhaps by using group by somehow? Thank you.
Not exactly sure if i am following, but try something like this:
select datepart(hh, getdate()) , count(*)
from broadcasts
where datepart(hh, starttime) <=datepart(hh, endtime)
and cast(starttime as date)=cast(getdate() as date) and cast(endtime as date)=cast(getdate() as date)
group by datepart(hh, getdate())
Join with a subquery that returns all the hour numbers:
SELECT h.hour_num, COUNT(*) AS total_online
FROM (SELECT 0 AS hour_num UNION SELECT 1 UNION SELECT 2 ... UNION SELECT 23) AS h
JOIN broadcasts AS b ON HOUR(b.start_time) = h.hour_num OR HOUR(b.end_time) >= h.hour_num
WHERE DATE(b.start_time) = '2018-01-01'
GROUP BY h.hour_num
I am trying to make simple MySQL query to display upcoming birthdays using below query. How to exclude/remove previous(yesterday) day from showing.
CREATE TABLE users (
name VARCHAR(100),
birthday DATE
);
INSERT INTO users (name, birthday) VALUES
('kostas', '1983-10-08'),
('kostas', '1983-10-11'),
('yannis', '1979-10-13'),
('natalia', '1980-10-15'),
('kostas', '1983-10-12'),
('Moskas', '1978-10-14'),
('Rasman', '1978-10-13'),
('natalia', '1980-10-18'),
('natalia', '1980-10-16');
Query:
SELECT *
FROM
users
WHERE
birthday != '' AND ABS(DAY(CURDATE()) - DAY(birthday)) < 2
ORDER BY
DAY(birthday)
Demo: sqlfiddle
You have to use BETWEEN instead of ABS. The absolute value do not return what you want, the between 0 and "days before the birthday" (2) is the right way to get days until birthday.
You also have to use DAYOFYEAR instead of DAY and you have to reverse the order of the subtraction terms DAYOFYEAR(birthday) - DAYOFYEAR(CURDATE())
To workaround leap years birthdays, as suggested here, birthday year should be converted to current year with:
DAYOFYEAR(DATE_ADD(e.birthdate, INTERVAL (YEAR(NOW()) - YEAR(birthday)) YEAR))
The final SQL is:
SELECT *
FROM
users
WHERE
birthday != '' AND (DAYOFYEAR(DATE_ADD(birthday, INTERVAL (YEAR(NOW()) - YEAR(birthday)) YEAR))-DAYOFYEAR(CURDATE())) between 0 and 2
ORDER BY
DAY(birthday)
I'd do it this way:
Transfer the birthdays to the current year and then define the datediff you want:
SELECT *,
DATEDIFF(str_to_date(CONCAT(YEAR(curdate()), '-', MONTH(birthday), '-', DAY(birthday)), '%Y-%m-%d'), curdate()) AS `days until birthday`
FROM users
WHERE DATEDIFF(str_to_date(CONCAT(YEAR(curdate()), '-', MONTH(birthday), '-', DAY(birthday)), '%Y-%m-%d'), curdate()) BETWEEN 1 AND 5 ;
I have used this previously, hope it will help others.
SELECT name, birthday, DATE_ADD(birthday, INTERVAL IF(DAYOFYEAR(birthday) >= DAYOFYEAR(CURDATE()), YEAR(CURDATE())-YEAR(birthday), YEAR(CURDATE())-YEAR(birthday)+1) YEAR ) AS next_birthday
FROM users
WHERE birthday!= '' AND disabled = '0'
HAVING next_birthday BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 3 DAY)
ORDER BY next_birthday
I need to create a query that looks like this image with the result:
You can ignore the names of the user, user_id is fine for now. Each user can have several timesheets for one day. So I need to count the hours and place it in its own column for day of the week. Then have a total at the end. Here is a screen shot of the database:
Here is what I have so far that gets me the days of the week totals but not grouped in one record with the day of the week as its own column and a total. Any help would be appreciated. Thanks!
SELECT user_id, WEEKDAY(start_date) AS day, (select time_to_sec(timediff(end_date, start_date )) / 3600) AS hours FROM `timesheet_table` WHERE id > 0 GROUP BY day, user_id
If you need a totat you can use a sum and group by
In Group by you can't use the alias but you should use the expression
SELECT
user_id
, WEEKDAY(start_date) AS day
, sum((select time_to_sec(timediff(end_date, start_date )) / 3600)) AS hours
FROM `timesheet_table`
WHERE id > 0
GROUP BY WEEKDAY(start_date), user_id
E.g.:
SELECT user_id
, DATE(start_date) dt
, SEC_TO_TIME(SUM(TIME_TO_SEC(end_date)-TIME_TO_SEC(start_date))) day_total
-- [or , SUM(TIME_TO_SEC(end_date)-TIME_TO_SEC(start_date))/3600 day_total]
FROM my_table
WHERE start_date BETWEEN '2016-10-01 00:00:00' AND '2016-10-07 23:59:59'
GROUP
BY user_id
, DATE(start_date);
The rest of the problem (missing days, display issues, weekly totals, etc.) would normally be handled in application level code.
I have a table tbl_subscriptions and columns like this "id, user_name, join_date(date)", I want to select the users before 7 days every month based on join_date so that I can send them notifications to continue their subscription for the next month. I have records like this
1, user1, 2014-05-02
2, user2, 2014-05-04
3, user3, 2014-06-12
4, user4, 2014-06-20
4, user5, 2014-07-24
If today is 2014-07-28, then I want to get records 1 and 2. I tried below query
SELECT *,
datediff( date_format(date, '2014-07-%d'), now() ) as daysLeft
FROM tbl_subscriptions
HAVING daysLeft >= 0
AND daysLeft < 7
the problem with above sql is that it is selecting the record of the current month only, plz suggest any better query.
Does this do what you want?
SELECT s.*, datediff(date, curdate()) as daysLeft
FROM tbl_subscriptions s
WHERE date >= curdate() and date < curdate() + interval 7 day;
EDIT:
I see. These are recurrent subscriptions and you want to find the next ones. The following logic should work:
select s.*,
(case when day(date) >= day('2014-07-28')
then day(date) - day('2014-07-28')
else day(date) + day(last_day('2014-07-28')) - day('2014-07-28')
end) as diff
from tbl_subscriptions s
having diff <= 7;
Here is the SQL Fiddle.
Ok, first of all I dont know what is subscription renewal period. And idea of only checking date (and not the whole period) doesnt make sense to me.
But this will get you your required output.
SELECT *,
day(date) days,
day(last_day('2014-07-28')) as lastday,
day('2014-07-28') today, day(last_day('2014-07-28'))-day('2014-07-28') as diff
FROM tbl_subscriptions
having days <= (7-diff) or (days > today and days <= today+7)
And here goes the demo (schema thanks to one of the deleted answer) ->
http://sqlfiddle.com/#!2/3cc4f
I have a table
id user Visitor timestamp
13 username abc 2014-01-16 15:01:44
I have to 'Count' total visitors for a 'User' for last seven days group by date(not timestamp)
SELECT count(*) from tableA WHERE user=username GROUPBY __How to do it__ LIMIT for last seven day from today.
If any day no visitor came so, no row would be there so it should show 0.
What would be correct QUERY?
There is no need to GROUP BY resultset, you need to count visits for a week (with unspecified user). Try this:
SELECT
COUNT(*)
FROM
`table`
WHERE
`timestamp` >= (NOW() - INTERVAL 7 DAY);
If you need to track visits for a specified user, then try this:
SELECT
DATE(`timestamp`) as `date`,
COUNT(*) as `count`
FROM
`table`
WHERE
(`timestamp` >= (NOW() - INTERVAL 7 DAY))
AND
(`user` = 'username')
GROUP BY
`date`;
MySQL DATE() function reference.
Try this:
SELECT DATE(a.timestamp), COUNT(*)
FROM tableA a
WHERE a.user='username' AND DATEDIFF(NOW(), DATE(a.timestamp)) <= 7
GROUP BY DATE(a.timestamp);
i think it's work :)
SELECT Count(*)
from table A
WHERE user = username AND DATEDIFF(NOW(),timestamp)<=7