Getting Max date from the given two dates in mysql - mysql

I have a table with below structure and data.
id ean Control_date qty
1 4046228081410 26.05.2017 568
2 4046228081410 05.06.2017 900
My expected result would be like below
2 4046228081410 05.06.2017 1468
To acheive this i am using the below query
SELECT EAN,Control_date,SUM(Qty) AS Qty FROM mytable WHERE
(STR_TO_DATE(`Control_date`,'%d.%m.%Y') <= STR_TO_DATE('03.06.2017','%d.%m.%Y')
OR
STR_TO_DATE(`Control_date`, '%d.%m.%Y') <= DATE_ADD(STR_TO_DATE('03.06.2017', '%d.%m.%Y'), INTERVAL 7 DAY))
AND ean = 4046228081410
Here i need to sum up the qty where control date< today date and control date > today date and should be less than todaydate + 7 days . Here 2nd control date is 05.06.2017 and greater than today date and less than (03.05.2017 +7 days)
But always i am getting where contorl date is less than today date.
1 4046228081410 26.05.2017 1468
But i need data with control date 05.06.2017.
Any help would be greatly appreciated.

You should really fix your date formats. If you stored the value as a date, the query would simply be:
SELECT EAN, MAX(Control_date), SUM(Qty) AS Qty
FROM mytable
WHERE Control_date < CURDATE() + INTERVAL 7 DAYS AND
Control_date >= CURDATE() AND
ean = 4046228081410
GROUP BY ean;
Note: You can use a constant such as '2017-06-03' if you want a constant date. However, your question specifically says the current date.
Just because you have bogus date formats stored in your data doesn't mean you have to use the same format in queries. The expression '2017-06-03' (or DATE('2017-06-03')) is simpler than the more complex STR_TO_DATE() expression.
In your case, bite the bullet and output the date in a correct format, so you can do:
SELECT EAN, MAX(STR_TO_DATE(`Control_date`, '%d.%m.%Y')), SUM(Qty) AS Qty
FROM mytable
WHERE STR_TO_DATE(`Control_date`, '%d.%m.%Y') < CURDATE() + INTERVAL 7 DAYS AND
STR_TO_DATE(`Control_date`, '%d.%m.%Y') >= CURDATE() AND
ean = 4046228081410
GROUP BY ean;

You have a typo in your SQL statement, and if you do not want today's date, then use less and greater
SELECT EAN,Control_date,SUM(Qty) AS Qty FROM mytable WHERE
(STR_TO_DATE(`Control_date`,'%d.%m.%Y') **<** STR_TO_DATE('03.06.2017','%d.%m.%Y')
OR
STR_TO_DATE(`Control_date`, '%d.%m.%Y') **>** DATE_ADD(STR_TO_DATE('03.06.2017', '%d.%m.%Y'), INTERVAL 7 DAY))
AND ean = 4046228081410

A couple of issues in your statement.
Date conditions are redundant
Need a MAX function on Control_date
Need group by n EAN
SELECT
EAN,
max(Control_date) AS control_date,
SUM(Qty) AS Qty
FROM mytable
WHERE
STR_TO_DATE(Control_date, '%d.%m.%Y') <= DATE_ADD(STR_TO_DATE('03.06.2017', '%d.%m.%Y'), INTERVAL 7 DAY)
AND
ean = 4046228081410
GROUP BY EAN

Related

SQL how to count distinct id in changing time ranges

I want to count the distinct number of fd_id over the time between today and yesterday, between today and 3 days ago, between today and 5 days ago, between today and 7 days ago, between today and 15 days ago, between today and 30 days ago.
My data table looks like the following:
user_id. fd_id. date
1. 123a. 20201010
1. 123a. 20201011
1. 124a. 20201011
...
and the desired result is of the following format:
user_id count_fd_id_1d count_fd_id_3d ... count_fd_id_30d
Specifically, I know I can do the following 6 times and join them together (some column bind method):
select user_id, count(distinct fd_id) as count_fd_id_1d
from table
where date <= today and date >= today-1 (#change this part for different dates)
select user_id, count(distinct fd_id) as count_fd_id_3d
from table
where date <= today and date >= today-3 (#change this part for different dates)
...
I am wondering how I may do this in one shot without running almost identical code for 6 times.
You can use conditional aggregation:
select user_id,
count(distinct case when date >= current_date - 1 day and date < current_date then fd_id end) as cnt_1d,
count(distinct case when date >= current_date - 3 day and date < current_date then fd_id end) as cnt_3d,
...
from mytable
goup by user_id
You can play around with the date expressions to set the ranges you want. The above works on entire days, and does not include the current day.
If the date column in the the table really does look like that (not in date/datetime format), I think you need to use STR_TO_DATE() to convert it to date format then uses DATEDIFF to check the date differences. Consider this example query:
SELECT user_id,
MAX(CASE WHEN ddiff=1 THEN cn END) AS count_fd_id_1d,
MAX(CASE WHEN ddiff=2 THEN cn END) AS count_fd_id_2d,
MAX(CASE WHEN ddiff=3 THEN cn END) AS count_fd_id_3d,
MAX(CASE WHEN ddiff=4 THEN cn END) AS count_fd_id_4d,
MAX(CASE WHEN ddiff=5 THEN cn END) AS count_fd_id_5d
FROM (SELECT user_id,
DATEDIFF(CURDATE(), STR_TO_DATE(DATE,'%Y%m%d')) ddiff,
COUNT(DISTINCT fd_id) cn
FROM mytable
GROUP BY user_id, ddiff) A
GROUP BY user_id;
At the moment, if you check date value simply by using direct subtraction, you'll get incorrect result. For example:
*your current date value - how many days:
'20201220' - 30 = '20201190' <-- this is not correct.
*if you convert the date value and using the same subtraction:
STR_TO_DATE('20201220','%Y%m%d') - 30 = '20201190' <-- still get incorrect.
*convert date value then uses INTERVAL for the date subtraction:
STR_TO_DATE('20201220','%Y%m%d') - INTERVAL 30 DAY = '2020-11-20'
OR
DATE_SUB(STR_TO_DATE('20201220','%Y%m%d'),INTERVAL 30 DAY) = '2020-11-20'
*IF your date column is storing standard date format value, then omit STR_TO_DATE
'2020-12-20' - INTERVAL 30 DAY = '2020-11-20'
OR
DATE_SUB('2020-12-20',INTERVAL 30 DAY) = '2020-11-20'
Check out more date manipulation in MySQL.
For the question, I made a fiddle with a bunch of testing.

Get yesterday date in SQL

i am try to request date only yesterday but without success...
My query request.
SELECT registeredDaySell FROM new_sell WHERE DATE_SUB(CURDATE(), INTERVAL 1 DAY)
My date is organized this way.
16 September, 2017
Thanks for helping me out.
subdate(now(),1) will return yesterdays timestamp
The below code will select all rows with yesterday's timestamp from employee_login page
Select * FROM `employee_login` WHERE `dattime` <= subdate(now(),1) AND `dattime` > subdate(now(),2)
The below code will display yesterday's timestamp
Select subdate(now(),1) ,subdate(now(),2))
This will give
SELECT producFinalPrice
FROM new_sell
WHERE WEEK (date) = WEEK( current_date ) - 1
As #Gordon mentioned, you should consider storing your dates either in some date type column, or possibly as a UNIX timestamp (seconds since the epoch). A possible workaround here would be to use STR_TO_DATE to convert your string dates to bona fide dates on the fly.
SELECT
producFinalPrice
FROM new_sell
WHERE
STR_TO_DATE(date_col, '%d %M, %Y') = DATE_SUB(CURDATE(), INTERVAL 1 DAY)
This assumes that date_col is the name of the column in your table which contains string dates.
SELECT producFinalPrice FROM new_sell
WHERE where date >= DATEADD(day, -1, convert(date, GETDATE()))
and date < convert(date, GETDATE())
-1 equates to "today" minus 1 day. You can change that number to get the number of days that you want to go back if further than 1.

SELECT from database date where date is today and multiple

There are a method with SQL to SELECT from one database the date records where the date is today and the date is multiple of two years.
For example, i have a table call "list". That table have two column, 'ID' and 'last_date'. One of this record is: ID = '1' and date = '17-03-2015'
I need to select all record where the date is the date on the table + 2 year. For example today the query will return the ID 1.
Thanks to all.
Use DATE_SUB() to subtract 2 years from today's date, and compare that to the column.
SELECT id
FROM list
WHERE last_date = DATE_SUB(CURDATE(), INTERVAL 2 YEAR);
This is a little better than #Teja's solution because it only has to do the date arithmetic once, rather than for every row in the table. And if there's an index on the last_date column, it will be able to use it to find the rows quickly.
We can write an expression that returns a date value that is exactly two days before today's date:
SELECT DATE(NOW()) + INTERVAL -2 YEAR
We can use an expression in the WHERE clause of a query. If the column in the table we want to check is defined as DATE datatype:
SELECT t.id
FROM mytable t
WHERE t.mydatecol = DATE(NOW()) + INTERVAL -2 YEAR
If it's defined as a DATETIME, the normal pattern would be range check
SELECT t.id
FROM mytable t
WHERE t.mydatecol >= DATE(NOW()) + INTERVAL -2 YEAR
AND t.mydatecol < DATE(NOW()) + INTERVAL -2 YEAR + INTERVAL 1 DAY
If the column is stored as a VARCHAR in a non-canonical format e.g. DD-MM-YYYY then we could either attempt to convert that to a DATE using STR_TO_DATE (which we don't like to do because the query can't make effective use of a index), or we could convert our generated date value into the required string format for an equality comparison:
SELECT t.id
FROM mytable t
WHERE t.ddmmyyyy = DATE_FORMAT(DATE(NOW()) + INTERVAL -2 YEAR,'%d-%m-%Y')
That would get us exact match to '17-03-2015', but not to '17-3-2015'. And we have to do equality test or IN list, we can't do range check, because the value stored in the column isn't canonical.
If we need to look for multiple dates... today, two years ago, four years ago, six years ago, ... we can generate a list of dates and perform a join operation. (Assuming that mydatecol is defined as DATETIME...)
SELECT t.id
FROM ( SELECT DATE(NOW()) + INTERVAL 0 YEAR AS dt
UNION ALL SELECT DATE(NOW()) + INTERVAL -2 YEAR
UNION ALL SELECT DATE(NOW()) + INTERVAL -4 YEAR
UNION ALL SELECT DATE(NOW()) + INTERVAL -6 YEAR
UNION ALL SELECT DATE(NOW()) + INTERVAL -8 YEAR
UNION ALL SELECT DATE(NOW()) + INTERVAL -10 YEAR
UNION ALL SELECT DATE(NOW()) + INTERVAL -12 YEAR
UNION ALL SELECT DATE(NOW()) + INTERVAL -14 YEAR
UNION ALL SELECT DATE(NOW()) + INTERVAL -16 YEAR
UNION ALL SELECT DATE(NOW()) + INTERVAL -18 YEAR
UNION ALL SELECT DATE(NOW()) + INTERVAL -20 YEAR
) l
JOIN mytable t
WHERE t.mydatecol >= l.dt + INTERVAL 0 DAY
AND t.mydatecol < l.dt + INTERVAL 1 DAY

Count of records for the last and current month unix timestamp

I need to make statistics page for billing with auto query. For example now is july and query must show count of record for the june and current count of records on current day(only july). Sort of:
"records for the last month - 85, for the current day - 32"
I have table customer and row create_time but it is in unix timestamp. Tried
SELECT COUNT(*) FROM customer WHERE create_time >=
UNIX_TIMESTAMP(DATE_SUB(now(), INTERVAL 1 MONTH))
but its absolutely not what i want.
I would appreciate for any help.
Try this:
SELECT *
FROM ( SELECT COUNT(*) AS total_previous_month
FROM customer
WHERE create_time >= concat(date_format(LAST_DAY(now() - interval 1 month),'%Y-%m-'),'01')
AND create_time < LAST_DAY(now() - interval 1 month )
) AS s1,
( SELECT COUNT(*) AS total_previous_month
FROM customer
WHERE create_time >= concat(extract(year from now()),'-',extract(month from now()),'-01')
AND create_time <= now()
) AS s2
You can do this by adding condition to the WHERE:
create_time >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL 1 month))
in PHP you can calculate the one month back date
$newDate = strtotime('-1 month');
and use this in query

SQL Count Totals Within Date Ranges

I have a CHANGES table with fields VALUE(integer) and CREATED_AT(timestamp). I want to know the total of the VALUE column grouped by each of the past 30 days (without making 30 queries).
So if yesterday there were records created with VALUEs of 10, -7, and 12; I would want a record returned with CREATED_AT = yesterday and TOTAL = 15.
Any help?
SELECT date(created_at) as CREATED_AT, sum(value) as TOTAL
FROM changes
WHERE created_at >= curdate() - interval 30 day
GROUP BY date(created_at);
Well, it slightly depends on what kind the timestamp is formatted in (SQL/ Unix/ etc). But this type of query might help you along:
SELECT
DATE_FORMAT(CREATED_AT, '%Y-%m-%d') ym,
COUNT(VALUE)
FROM foo
GROUP BY ym