MYSQL - Update row when the date more than 1 year - mysql

I am had a query could able to update the row if DateTimeAdded is 1 year or more. But i find out that it wouldn't work in leap year. Anyone have better suggestion?
CREATE EVENT UpdateProduct
ON SCHEDULE
EVERY 1 DAY
DO
update `product` set Label = "ClearStock" where datediff(now(),
DateTimeAdded) >= 365

To identify rows that have DateTimeAdded value over a year old, you could do something like this:
... WHERE DateTimeAdded < NOW() + INTERVAL -1 YEAR
FOLLOWUP
Demonstration:
SELECT NOW() + INTERVAL 0 HOUR AS `now`
, DATE(NOW()) + INTERVAL -1 YEAR AS `year_ago`
, t.DateTimeAdded
, t.DateTimeAdded < DATE(NOW()) + INTERVAL -1 YEAR AS `compare`
FROM ( SELECT '2015-01-24 11:00:00' AS `DateTimeAdded`
UNION ALL
SELECT '2015-01-25 13:00:00'
UNION ALL
SELECT '2015-01-26 14:00:00'
) t
returns:
NOW year_ago DateTimeAdded compare
------------------- ---------- ------------------- -------
2016-01-25 22:11:56 2015-01-25 2015-01-24 11:00:00 1
2016-01-25 22:11:56 2015-01-25 2015-01-25 13:00:00 0
2016-01-25 22:11:56 2015-01-26 2015-01-26 14:00:00 0

Related

How to retrieve data from previous 4 weeks (mySQL)

I am trying to write a query to get the last 4 weeks (Mon-Sun) of data. I want every week of data to be stored with an individual and shared table.
every week data store based on name if same name repeated on single week amt should sum and if multiple name it should be show data individual, To see an example of what I am looking for, I have included the desired input and output below.
this is my table
date
amt
name
2022-04-29
5
a
2022-04-28
10
b
2022-04-25
11
a
2022-04-23
15
b
2022-04-21
20
b
2022-04-16
20
a
2022-04-11
10
a
2022-04-10
5
b
2022-04-05
5
b
i want output like this
date
sum(amt)
name
2022-04-25 to 2020-04-29
16
a
2022-04-25 to 2020-04-29
10
b
2022-04-18 to 2022-04-24
35
b
2022-04-11 to 2022-04-17
30
a
2022-04-04 to 2022-04-10
10
b
I would appreciate any pointers or 'best-practises' which I should employ to achieve this task.
You can try to use DATE_ADD with WEEKDAY get week first day and end day.
SELECT
CASE WHEN
weekofyear(`date`) = weekofyear(NOW())
THEN 'current week'
ELSE
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d'))
END 'date',
SUM(amt)
FROM T
GROUP BY
CASE WHEN
weekofyear(`date`) = weekofyear(NOW())
THEN 'current week'
ELSE
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d'))
END
sqlfiddle
EDIT
I saw you edit your question, you can just add name in group by
SELECT
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d')) 'date',
SUM(amt),
name
FROM T
GROUP BY
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d')),
name
ORDER BY 1 desc
sqlfiddle
This is in SQL Server, and just a mess about. Hopefully it can be of some help.
with cteWeekStarts
as
(
select
n,dateadd(week,-n,DATEADD(week, DATEDIFF(week, -1, getdate()), -1)) as START_DATE
from
(values (1),(2),(3),(4)) as t(n)
), cteStartDatesAndEndDates
as
(
select *,dateadd(day,-1,lead(c.start_date) over (order by c.n desc)) as END_DATE
from cteWeekStarts as c
)
,cteSalesSumByDate
as
(
select s.SalesDate,sum(s.salesvalue) as sum_amt from
tblSales as s
group by s.SalesDate
)
select c3.n as WeekNum,c3.START_DATE,isnull(c3.END_DATE,
dateadd(day,6,c3.start_date)) as END_DATE,
(select sum(c2.sum_amt) from cteSalesSumByDate as c2 where c2.SalesDate
between c3.START_DATE and c3.END_DATE) as AMT
from cteStartDatesAndEndDates as c3
order by c3.n desc

Query to select days until a certain date

Either my brain isn't functioning the way it should today or this is actually a hard thing to do.
I've got the following table containing my users.
id | name | birthdate |
------+----------+------------
1 | John | 1990-08-27
2 | Jane | 1985-08-29
3 | Joe | 1985-08-31
birthdate is a date column in the above table.
I'd like to get the users that have their birthday today or in previous days including the weekend.
I've come no further than the following attempt:
SELECT
*
FROM users
WHERE (DATE_FORMAT(users.birthdate, '%d-%m') IN (
'29-08',
'28-08',
'27-08',
'26-08'
)
Can any of you help me out with a query?
This query should do what you want. First it translates the user's birthdate to the current year:
STR_TO_DATE(CONCAT(YEAR(CURRENT_DATE()), DATE_FORMAT(birthdate, '-%m-%d')), '%Y-%m-%d')
then it sees if that date is between today (CURRENT_DATE()) and last Saturday:
CURRENT_DATE() - INTERVAL (WEEKDAY(CURRENT_DATE()) - 5 + 7) % 7 DAY
Full query:
SELECT *
FROM users
WHERE STR_TO_DATE(CONCAT(YEAR(CURRENT_DATE()), DATE_FORMAT(birthdate, '-%m-%d')), '%Y-%m-%d') BETWEEN
CURRENT_DATE() - INTERVAL (WEEKDAY(CURRENT_DATE()) - 5 + 7) % 7 DAY AND CURRENT_DATE()
SQLFiddle Demo
SELECT *
FROM users
WHERE DATE(users.birthdate + INTERVAL (YEAR(NOW()) - YEAR(users.birthdate)) YEAR)
BETWEEN
DATE(NOW() - INTERVAL WEEKDAY(NOW()) DAY)
AND
DATE(NOW() + INTERVAL 6 - WEEKDAY(NOW()) DAY);
http://www.sqlfiddle.com/#!9/71573/7
use NOW() - INTERVAL WEEKDAY(birthdate) +2 DAY get last Saterday Date.
Then use day and month function to get the day and month number, then check in where clause.
month(birthdate) is the same as NOW() month,
day number from last Saturday to NOW()
You can try this.
CREATE TABLE users(
id INT,
name VARCHAR(50),
birthdate DATE
);
INSERT INTO users VALUES (1,'John' , '1990-08-27');
INSERT INTO users VALUES (2,'Jane' , '1985-08-29');
INSERT INTO users VALUES (22,'Joe' , '1985-05-31');
INSERT INTO users VALUES (33,'Joe' , '1985-08-11');
INSERT INTO users VALUES (3,'Joe' , '1985-08-31');
Query 1:
SELECT *
FROM users
WHERE
month(birthdate) = month(NOW())
AND
day(birthdate) between day(NOW() - INTERVAL WEEKDAY(birthdate) +2 DAY) and day(NOW())
Results:
| id | name | birthdate |
|----|------|------------|
| 1 | John | 1990-08-27 |
| 2 | Jane | 1985-08-29 |
Try this query: curdate() - INTERVAL DAYOFWEEK(curdate()) this will give you date including saturday
SELECT * FROM users
WHERE day(users.birthdate)>=day(curdate() - INTERVAL DAYOFWEEK(curdate())) and <=day(curdate()) and (month(users.birthdate)=month(curdate()) or month(users.birthdate)=month(curdate() - INTERVAL DAYOFWEEK(curdate())))

Getting data from the last 12 month using mysql

I have the following data structure in my table:
id member_from member_till
1 2014/03/01 2014/05/18
2 2014/01/09 2014/08/13
...
How can i get a count of active members for the last 12 month, grouped by month?
Ex:
...
2014/12/01,5
2015/01/01,12
As a future development is it possible to make the count the average of the first and last day of each month?
First of all you need the last twelve months. Then outer-join the members and count those where the month is in the membership range.
select
date_format(all_months.someday, '%Y %m') as mymonth,
count(membership.member_from) as members
from
(
select current_date as someday
union all
select date_add(current_date, interval -1 month)
union all
select date_add(current_date, interval -2 month)
union all
select date_add(current_date, interval -3 month)
union all
select date_add(current_date, interval -4 month)
union all
select date_add(current_date, interval -5 month)
union all
select date_add(current_date, interval -6 month)
union all
select date_add(current_date, interval -7 month)
union all
select date_add(current_date, interval -8 month)
union all
select date_add(current_date, interval -9 month)
union all
select date_add(current_date, interval -10 month)
union all
select date_add(current_date, interval -11 month)
) all_months
left join membership
on date_format(all_months.someday, '%Y %m')
between
date_format(membership.member_from, '%Y %m')
and
date_format(membership.member_till, '%Y %m')
group by date_format(all_months.someday, '%Y %m');
SQL fiddle: http://www.sqlfiddle.com/#!2/6dc5a/10.
As to your future requirement: You can join the membership table twice, once for the members on the first of a month, once for the last of the month (loosing those who participated only some days in the middle of a month). Then add both counts and divide by two.
You can try with SQL Query:
SELECT `member_from`, count(id) FROM tbl_test WHERE `member_from` BETWEEN <From date> AND <To date> GROUP BY `member_from`;
Complete with future requirement:
SELECT
d.ymonth,
COUNT(m.member_from) total,
COALESCE(SUM(d.fday BETWEEN m.member_from AND m.member_till), 0) total_fom,
COALESCE(SUM(d.lday BETWEEN m.member_from AND m.member_till), 0) total_lom
FROM
(
SELECT
CAST(#first_day := #first_day + INTERVAL 1 MONTH AS DATE) fday,
LAST_DAY(#first_day) lday,
DATE_FORMAT(#first_day, '%Y-%m') ymonth
FROM
information_schema.collations
CROSS JOIN
(SELECT #first_day := LAST_DAY(CURRENT_DATE) - INTERVAL 13 MONTH + INTERVAL 1 DAY) x
LIMIT 12
) d
LEFT JOIN
membership m
ON d.lday >= m.member_from
AND d.fday <= m.member_till
GROUP BY d.ymonth
The subquery generates a virtual lookup table with 3 columns:
+ ---------- + ---------- + ------- +
| fday | lday | ymonth |
+ ---------- + ---------- + ------- +
| 2014-02-01 | 2014-02-28 | 2014-02 |
| \/ | \/ | \/ |
| 2015-01-01 | 2015-01-31 | 2015-01 |
+ ---------- + ---------- + ------- +
Then the membership table can be joined on the overlaps member_from-member_till and the beginning and ending of each month.

How can i get two row from 1 in duration mysql?

I have rows like:
id, start_date, end_date
0, 2000-01-01 20:00:00, 2000-01-01 21:00:00
1, 2000-01-01 23:00:00, 2000-01-02 04:00:00
And I need get reporting result like:
date | time_online
2000-01-01 | 02:00:00
2000-01-02 | 04:00:00
My solution was wrong cos i only start_date count.
SELECT DATE_FORMAT(start_date, '%Y-%m-%d') as date,
SUM(CASE WHEN EXTRACT(DAY FROM start_date) <> EXTRACT(DAY FROM end_date)
THEN
TIMESTAMPDIFF(SECOND, start_date, DATE_FORMAT(start_date + INTERVAL 1 DAY, '%Y-%m-%d'))
ELSE
TIMESTAMPDIFF(SECOND, start_date, end_date) END) time_online
FROM online
GROUP BY date
Result:
date | time_online
2000-01-01 | 02:00:00
Can someone help me?
What you need is a (virtual) reference table with a 24 hour timespan for each date in the online table.
You can use the table itself to do that:
SELECT
DATE(start_date) + INTERVAL 0 HOUR ref_start,
DATE(start_date) + INTERVAL 24 HOUR ref_end
FROM
online
WHERE
end_date IS NOT NULL
UNION DISTINCT
SELECT
DATE(end_date) + INTERVAL 0 HOUR ref_start,
DATE(end_date) + INTERVAL 24 HOUR ref_end
FROM
online
WHERE
end_date IS NOT NULL
The + INTERVAL 0 HOUR is not really neccesary, I added that for clarity, the same goes for the DISTINCT keyword.
If you put this in a subquery then you can get with a (kind of) self-join the records with overlaps, and the calculate the difference depending on the the values:
SELECT
DATE(r.ref_start) ref_date,
SEC_TO_TIME(SUM(TIMESTAMPDIFF(SECOND,
CASE WHEN d.start_date >= r.ref_start
THEN d.start_date
ELSE r.ref_start
END,
CASE WHEN d.end_date <= r.ref_end
THEN d.end_date
ELSE r.ref_end
END))) time_online
FROM
(
SELECT
DATE(start_date) + INTERVAL 0 HOUR ref_start,
DATE(start_date) + INTERVAL 24 HOUR ref_end
FROM
online
WHERE
end_date IS NOT NULL
UNION DISTINCT
SELECT
DATE(end_date) + INTERVAL 0 HOUR ref_start,
DATE(end_date) + INTERVAL 24 HOUR ref_end
FROM
online
WHERE
end_date IS NOT NULL
) r
JOIN
online d
ON d.end_date > r.ref_start
AND d.start_date < r.ref_end
GROUP BY ref_date

MySQL query problem. Last MONTH dates

I have a dateBill field -DATETIME- in my DB.
I would like to retrieve all the info from THE LAST MONTH.
So, today is: 2011-08-02 12:00:00
My query is:
SELECT *
FROM bills
WHERE DATE(dateBill) > DATE_SUB(CURDATE(), INTERVAL 1 MONTH) AND status = 1
ORDER BY id_bill
The status just says if the bill is approved or not.
But I get some weid results:
2011-09-01 21:44:07
2012-08-01 00:00:00
I inserted those values just to test. As you can see, it is not working.
Any help, please?
DATE(dateBill) > DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
captures dates in the future too.
including next month
2011-09-01 21:44:07
and next year
2012-08-01 00:00:00
add AND CURDATE() <= DATE(dateBill) if you dont like that...
SELECT *
FROM bills
WHERE
YEAR(dateBill) = YEAR(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) AND
MONTH(dateBill) = MONTH(DATE_SUB(CURDATE(), INTERVAL 1 MONTH)) AND
status = 1
ORDER BY id_bill