MySql select 1 week & 1 Month advance date from Current date - mysql

i want to get the list of date which is going to expire in a week or a month...
MySQL, and field is TIMESTAMP.
i tried below queries...
SELECT CERT_ID, date(CERTVALIDITY)
FROM mst_CERT WHERE date(CERTVALIDITY) > now() - interval 1 week ORDER BY CERTVALIDITY;
This returns all the dates from current date
SELECT date(CERTVALIDITY) from mst_CERT where curdate() =
DATE(DATE_SUB(CERTVALIDITY, INTERVAL 1 week));
returns nothing...
SELECT date(DATE_SUB(CERTVALIDITY, INTERVAL 1 MONTH)) from mst_CERT;
returns nothing...
| CT00078 | 2020-02-28 |
| CT00098 | 2020-02-29 |
| CT00011 | 2020-03-31 |
| CT00012 | 2020-03-31 |
| CT00013 | 2020-03-31 |
| CT00014 | 2020-03-31 |
| CT00075 | 2020-03-31 |
| CT00055 | 2020-03-31 |
| CT00056 | 2021-03-31 |

This will show CERT_ID's outside of a 7 day period.
SELECT CERT_ID, date(CERTVALIDITY)
FROM mst_CERT
WHERE date(CERTVALIDITY) > (NOW() + INTERVAL 7 day)
ORDER BY date(CERTVALIDITY);
This will show you valid CERT_ID's within a 7 day period.
SELECT CERT_ID, date(CERTVALIDITY)
FROM mst_CERT
WHERE date(CERTVALIDITY) BETWEEN NOW() AND (NOW() + INTERVAL 7 day)
ORDER BY date(CERTVALIDITY);

Your first query is almost right. You made a mistake of subtracting interval of 1 week but you actually had to add interval.
SELECT CERT_ID, DATE(CERTVALIDITY)
FROM ms_CERT
WHERE DATE(CERTVALIDITY) < NOW() + INTERVAL 1 WEEK AND DATE(CERTVALIDITY) > NOW()
ORDER BY CERTVALIDITY;
Above Query will return following result
| CT00078 | 2020-02-28 |
| CT00098 | 2020-02-29 |

Related

select item from table and order by amount on 2 days?

For example I have below table:
---------------------
| amount | date |
---------------------
| 50 | Day 1 |
| 60 | day 2 |
| 20 | day 3 |
| 25 | day 3 |
| 23 | day 4 |
| 26 | day 4 |
| 15 | day 5 |
---------------------
What I basically want to do is to retrieve item from last 2 days and order the row by max amount. so the result would be like:
---------------------
| amount | date |
---------------------
| 26 | day 4 |
| 23 | day 4 |
| 15 | day 5 |
---------------------
FYI: the date input is in 2018-06-10 14:37:44 mode above is just an example
I tried: SELECT AMOUNT FROM table WHERE AMOUNT=(SELECT MAX(AMOUNT) FROM table) ORDER BY DATE;
But the result I am getting is only | 60 | day 2 | which is the max amount and is not from 2 recent dates;
You could use the DATE_ADD function that gives you a date after a certain time alongside CURDATE() that gives you current date;
SELECT * FROM table WHERE date >= DATE_ADD(CURDATE(), INTERVAL -2 DAY)
ORDER BY amount DESC;
Try this:
SELECT amount, date FROM table WHERE date >= DATE_ADD(CURDATE(), INTERVAL -2 DAY) ORDER BY amount DESC;
-- date > DATE_ADD(CURDATE(), INTERVAL -2 DAY) will give you all rows within 2 days
-- ORDER BY amount DESC will give you ordered by amount descending

How to get the data per month in MySQL

I'm trying to get the data per every month.
I'm a newbie at MySQL.
I just google and learn from the internet.
So, My Query may be not suitable.
If not suitable, please fix my query.
HERE IS MY QUERY
SELECT
SUM( cr_dt > EXTRACT( YEAR_MONTH FROM CURDATE() )
AND
cr_dt < EXTRACT( YEAR_MONTH FROM CURDATE() + INTERVAL 1 MONTH )
) as thisMonth,
SUM( cr_dt > EXTRACT( YEAR_MONTH FROM CURDATE() - INTERVAL 1 MONTH
AND
cr_dt < EXTRACT( YAER_MONTH FROM CURDATE()
) as last1Month
FROM MYTABLE
I just found the EXTRACT() and INTERVAL, but I don't know it may suitable.
If you have a better way to solve, share please.
WHAT I EXPECT
| thisMonth | last1Month |
+-----------+------------+
| 123 | 1294 |
WHAT I SEE NOW
| thisMonth | last1Month |
+-----------+------------+
| 0 | 0 |
SAMPLE DATAS
| idx | cr_dt |
+-----+---------------------+
| 1 | 2018-02-01 17:00:00 |
| 2 | 2018-02-19 16:00:00 |
| 3 | 2018-02-28 15:00:00 |
| 4 | 2018-03-04 14:00:00 |
| 5 | 2018-04-01 13:00:00 |
| 6 | 2018-04-09 12:00:00 |
| 7 | 2018-04-12 11:00:00 |
| 8 | 2018-04-17 10:00:00 |
You need to use conditional aggregation here, something like this:
SELECT
COUNT(CASE WHEN cr_dt >= DATE_FORMAT(CURRENT_DATE, '%Y/%m/01')
THEN 1 END) AS thisMonth,
COUNT(CASE WHEN cr_dt >= DATE_FORMAT(CURRENT_DATE - INTERVAL 1 MONTH, '%Y/%m/01') AND
cr_dt < DATE_FORMAT(CURRENT_DATE, '%Y/%m/01') THEN 1 END) AS last1Month
FROM MYTABLE
WHERE cr_dt >= DATE_FORMAT(CURRENT_DATE - INTERVAL 1 MONTH, '%Y/%m/01');
More typically you might see this sort of query using a GROUP BY clause, to compute aggregates over individual groups. In your case, however, it appears you want to aggregate over the entire table.

Select all records that were created on a given day N months ago

Given a table orders:
+-----+---------+-------------------------+
| id | price | created_at |
+-----+---------+-------------------------+
| 1 | 16.50 | 2017-02-28 12:52:00.824 |
| 2 | 22.00 | 2017-10-03 15:12:39.107 |
| 3 | 50.00 | 2017-12-03 12:54:42.658 |
| 4 | 12.00 | 2018-01-02 07:21:47.808 |
| . | . | . |
| . | . | . |
| . | . | . |
+-----+---------+-------------------------+
and current date:
+---------------------+
| NOW() |
+---------------------+
| 2018-01-03 10:33:14 |
+---------------------+
I'd like to select all records that were created on current day any months ago. So for above data my query should return:
+-----+---------+-------------------------+
| id | price | created_at |
+-----+---------+-------------------------+
| 2 | 22.00 | 2017-10-03 15:12:39.107 |
| 3 | 50.00 | 2017-12-03 12:54:42.658 |
+-----+---------+-------------------------+
But there are some edge cases for the last day of month:
if it's 31-days month, it's trivial
if it's 30-days month, the query should return all records created on 30th and 31st day of month
if it's February in a leap year, the query should return all records created on 29th, 30th and 31st day of month
if it's February in a normal year, the query should return all records created on 28th, 29th, 30th and 31st day of month
What I have tried is something like this:
SELECT * FROM orders
JOIN (
SELECT id, PERIOD_DIFF(
DATE_FORMAT(NOW(), "%Y%m"),
DATE_FORMAT(created_at, "%Y%m")
) AS diff
FROM orders
) AS periods
ON orders.id = periods.id
WHERE DATEDIFF(created_at + INTERVAL diff MONTH, NOW()) = 0;
But it doesn't cover the edge cases and I believe there is a smarter way (maybe without a subquery) to achieve the expected results.
EDIT:
To give you more context - what I need is a kind of a loop. I have a cron job scheduled to run once a day at midnight. This job should select all ids of orders that were created on this day any months ago and then refresh some other data associated with those ids. The important part is to refresh this data exactly once every month - that's why the last day of months is so crucial.
For example, given following creation dates:
DATES = [
2015-05-30, 2016-02-29, 2016-10-03,
2016-12-31, 2017-05-28, 2018-01-03
]
+---------------+------------------------------------+
| NOW() | SHOULD BE INCLUDED |
+---------------+------------------------------------+
| 2018-01-03 | 2016-10-03, 2018-01-03 |
| 2018-02-28 | 2016-02-29, 2016-12-31, 2017-05-28 |
| 2018-04-30 | 2015-05-30, 2016-12-31 |
| 2018-10-31 | 2016-12-31 |
+---------------+------------------------------------+
Can I suggest a slight simplification Walerian?
SELECT
*
FROM
orders
WHERE
(
DAYOFMONTH(created_at) = DAYOFMONTH( NOW() ) --monthdays that match
)
OR
(
( DAYOFMONTH( LAST_DAY( NOW() ) ) = DAYOFMONTH( NOW() ) ) --base date is end of month
AND
( DAYOFMONTH(created_at) > DAYOFMONTH( NOW() ) ) --target monthdays are beyond base monthday
)
Incidentally I don't have a MySQL environment, so I'm just taking it on trust that these are the correct functions in MySQL.
Use DAYOFMONTH() function to compare the day of the NOW() and the created_at.
Like this:
SELECT * FROM ORDERS
WHERE (DAYOFMONTH(NOW() < LAST_DAY(NOW()) -- if not last day of month
AND DAYOFMONTH(created_at) = DAYOFMONTH(NOW())
OR (LAST_DAY(NOW()) = DAYOFMONTH(NOW()) -- if last day of month
AND DAYOFMONTH(NOW()) BETWEEN DAYOFMONTH(created_at) AND LAST_DAY(created_at)) --
Inspired by suresubs's answer, I figured out how the query should look like.
SELECT * FROM orders
-- (1)
WHERE (DAYOFMONTH(NOW) < DAYOFMONTH(LAST_DAY(NOW()))
AND DAYOFMONTH(created_at) = DAYOFMONTH(NOW()))
-- (2)
OR (DAYOFMONTH(LAST_DAY(NOW())) = DAYOFMONTH(NOW())
AND DAYOFMONTH(created_at) BETWEEN DAYOFMONTH(NOW()) AND DAYOFMONTH(LAST_DAY(created_at)));
It's using DAYOFMONTH() and LAST_DAY() functions and it's divided into two cases:
Today is not the last day of current month.
Today is the last day of current month.

Format grouped date as readable date

So I have a query that correctly displays the number of registrations for the last 12 months. Here is display:
Registrations per month for last 2 years
1--17
2--12
3--17
4--8
5--9
6--8
7--15
8--20
9--12
10--14
11--13
12--14
But since im running this in say June, the last mont I need to say the readable date May and not '1'. I want instead:
May--17
Apr--12
March--17
.
.
.
Here is my current MYSQL:
SELECT MONTH(create_date) as month , COUNT(create_date) as count
FROM `users`
WHERE create_date >= NOW() - INTERVAL 1 YEAR
GROUP BY MONTH(create_date)
I assumed I just have to use FORMAT_DATE() on the GROUP By as:
GROUP BY FORMAT_DATE(MONTH(create_date, '%M'))
And that would give me my readable month, but the sql statement reports it is not correct. Anyone know how to accomplish this?
Try this:
SELECT DATE_FORMAT(create_date, '%M') AS month, COUNT(create_date) AS count
FROM users
WHERE create_date >= NOW() - INTERVAL 1 YEAR
GROUP BY MONTH(create_date);
The result will be:
+-----------+-------+
| month | count |
+-----------+-------+
| January | 1 |
| February | 1 |
| March | 1 |
| April | 1 |
| May | 2 |
| June | 2 |
| July | 1 |
| August | 1 |
| September | 1 |
| November | 1 |
| December | 1 |
+-----------+-------+
You can use STR_TO_DATE() to convert the number to a date, and then back with MONTHNAME()
SELECT MONTHNAME(create_date(6, '%m')) as month , COUNT(create_date) as count
FROM `users`
WHERE create_date >= NOW() - INTERVAL 1 YEAR
GROUP BY MONTH(create_date)

Group by date range on weeks/months interval

I'm using MySQL and I have the following table:
| clicks | int |
| period | date |
I want to be able to generate reports like this, where periods are done in the last 4 weeks:
| period | clicks |
| 1/7 - 7/5 | 1000 |
| 25/6 - 31/7 | .... |
| 18/6 - 24/6 | .... |
| 12/6 - 18/6 | .... |
or in the last 3 months:
| period | clicks |
| July | .... |
| June | .... |
| April | .... |
Any ideas how to make select queries that can generate the equivalent date range and clicks count?
SELECT
WEEKOFYEAR(`date`) AS period,
SUM(clicks) AS clicks
FROM `tablename`
WHERE `date` >= CURDATE() - INTERVAL 4 WEEK
GROUP BY period
SELECT
MONTH(`date`) AS period,
SUM(clicks) AS clicks
FROM `tablename`
WHERE `date` >= CURDATE() - INTERVAL 3 MONTH
GROUP BY period
For the last 3 months you can use:
SELECT MONTH(PERIOD), SUM(CLICKS)
FROM TABLE
WHERE PERIOD >= NOW() - INTERVAL 3 MONTH
GROUP BY MONTH(PERIOD)
or for the last 4 weeks:
SELECT WEEK(PERIOD), SUM(CLICKS)
FROM TABLE
WHERE PERIOD >= NOW() - INTERVAL 4 WEEK
GROUP BY WEEK(PERIOD)
Code not tested.