How to select last 7 days available - MySql - mysql

I am having problem with dealing with data in MySQL. How can I select all data from the pasty seven available data?
I tried to run
SELECT * FROM database where ship_day
BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY) AND NOW();
but I doesn't work for my purpose.
Let's say we are on January, 9th and my MAX(ship_day) is January, 7th and I want to pull data from the past 7 available data so from January 1st to 7th.
I tried to run
SELECT * FROM database where ship_day
BETWEEN DATE_SUB(MAX(ship_day), INTERVAL 7 DAY) AND MAX(ship_day);
but I got an error.
I know that I can increase INTERVAL 7 DAY to INTERVAL 9 DAY but I want this process to be automatic. How can I solve?

Well, here is one method:
SELECT d.*
FROM database d
WHERE d.ship_day >= COALESCE( (SELECT DISTINCT d2.ship_day
FROM database d2
ORDER BY d2.ship_day DESC
LIMIT 1 OFFSET 6
), d.ship_day
);
Note: If you have only one row per ship_day, then just use limit:
SELECT d.*
FROM database d
ORDER BY d.ship_day DESC
LIMIT 7

Let's say we are on January, 9th and my MAX(ship_day) is January, 7th
and I want to pull data from the past 7 available data so from January
1st to 7th.
I assume you are looking for the query below but hard to say for sure without example data and expected results.
SELECT
*
FROM
t
WHERE
ship_day >= (
SELECT
MAX(ship_day) - INTERVAL 7 DAY
FROM
t
)
Or you can also write this as
SELECT
*
FROM
t
WHERE
ship_day >= (
SELECT
MAX(ship_day)
FROM
t
) - INTERVAL 7 DAY

You can get the last date for which you have data with:
select MAX(ship_day) FROM database
so use it like this:
SELECT * FROM database
where ship_day >= DATE_SUB((select MAX(ship_day) FROM database), INTERVAL 7 DAY)

Related

SQL select by date from today

I'm studying SQL (Using MariaDB 10.2) and I'm using a huge example database I found online. It has an 'employees' table, and this one has a 'birth_date' column of 'date' type. I want to select all those employees who are more than 50 years old, for example, or maybe those who will be 25 years old on an specific date . Is there a way to do something like this?
You can add or subtract intervals to dates:
SELECT *
FROM employee
WHERE birth_date <= NOW() - INTERVAL 50 YEAR
Assuming t-sql, then for those over 50 today, use:
select * from employees where datediff(year, birth_date, now()) > 50
For those who will be 25 on a certain date use:
select * from employees where datediff(year, birthdate, certain_date) = 25
Use this
SELECT * FROM myTable WHERE DATE(myDate) = DATE(NOW())
This is for MySql DB
You can use INTERVAL function which you can add or subtract Dates:
SELECT * FROM employee WHERE birth_date <= (NOW() - INTERVAL 50 YEAR);
NOW() -----> Present Date
-INTERVAL 50 YEAR -----> Subtract that Date to 50 Years

Aggregating table data in MySQL, is there an easier way to do this?

I'm trying to write a query that aggregates data from a table.
Essentially I have a long list of devices that have been inventoried and eventually installed over the last couple of years.
I want to find the average amount of time between when the device was received and when it was installed, and then have that data sorted by the month the device was installed. BUT in each month's row, I also want to include the data from the previous months.
So essentially what I want to see is: (sorry for terrible formatting)
MonthInstalled | TimeToInstall | Total#Devices
-----------------+---------------+----------------------------
Jan | 10 Days | 5
Feb(=Jan+Feb) | 15 Days | 18 (5 in Jan + 13 in Feb)
Mar(=Jan+Feb+Mar)| 13 Days | 25 (5 + 13 + 7)
...
The query I currently have written looks like this:
INSERT INTO DevicesInstall
SELECT ROUND(AVG(DATEDIFF(dvc.dt_install , dvc.dt_receive)), 1) AS 'Install',
COUNT(dvc.dvc_model) AS 'Total Devices',
MAX(dvc.dt_install) AS 'Date',
loc.loc_campus AS 'Campus'
FROM dvc_info dvc, location loc
WHERE dvc.dvc_loc_bin = loc.loc_bin
AND dvc.dt_install < '20160201'
;
Although this is functional, I have to iterate this for each month manually, so it is not scale-able. Is there a way to condense this at all?
We can return the dates using an inline view (derived table), and then join to the dvc_info table, so we can get the "cumulative" results.
To get the results for:
Jan
Jan+Feb
Jan+Feb+Mar
We need to return three copies of the rows for Jan, and two copies of the rows for Feb, and then collapse the those rows into an appropriate group.
The loc_campus is being included in the SELECT list... not clear why that is needed. If we want results "by campus", then we need to include that expression in the GROUP BY clause. Otherwise, the value returned for that non-aggregate is indeterminate... we will get a value for some row "in the group", but it could be any row.
Something like this:
SELECT d.dt AS `before_date`
, loc.loc_campus AS `Campus`
, ROUND(AVG(DATEDIFF(dvc.dt_install,dvc.dt_receive)),1) AS `Install`
, COUNT(dvc.dvc_model) AS `Total Devices`
, MAX(dvc.dt_install) AS `latest_dt_install`
FROM ( SELECT '2016-01-01' + INTERVAL 1 MONTH AS dt
UNION ALL SELECT '2016-01-01' + INTERVAL 2 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 3 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 4 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 5 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 6 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 7 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 8 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 9 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 10 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 11 MONTH
UNION ALL SELECT '2016-01-01' + INTERVAL 12 MONTH
) d
CROSS
JOIN location loc
LEFT
JOIN dvc_info dvc
ON dvc.dvc_loc_bin = loc.loc_bin
AND dvc.dt_install < d.dt
GROUP
BY d.dt
, loc.loc_campus
ORDER
BY d.dt
, loc.loc_campus
Note that the value returned for d.dt will be the "up until" date. We're going to get '2016-02-01' returned for the January results. If we want to return a value of January date, we can use an expression in the SELECT list...
SELECT DATE_FORMAT(d.dt + INTERVAL -1 MONTH,'%Y-%m') AS `month`
Lots of options on query alternatives.
But it looks like the "big hump" is that to get cumulative results, we need to return multiple copies of the dvc_info rows, so the rows can be collapsed into each "grouping".
I recommend working on just the SELECT first. And get that tested working, before monkeying around to turn it into an INSERT ... SELECT.
FOLLOWUP
We can use any query as an inline view (derived table d) that returns a set of dates we want.
e.g.
FROM ( SELECT DATE_FORMAT(m.install_dt,'%Y-%m-01') + INTERVAL 1 MONTH AS dt
FROM dvc_install m
WHERE m.install_dt >= '2016-01-01'
GROUP BY DATE_FORMAT(m.install_dt,'%Y-%m-01') + INTERVAL 1 MONTH
) d
Note that with this approach, if there are no install_dt in February, we won't get back a row for February. Using the static UNION ALL SELECT approach allows us to get back "zero" counts, i.e. to return rows for months where there isn't an install_dt in that month. (But that's the answer to a different question... how do I get back a "zero" count for February when there aren't any rows for Februrary?)
Alternatively, if we have a calendar table e.g. cal that contains a list of the dates we want, we could just reference the table in place of the inline view, or the inline view query could get rows from that.
FROM ( SELECT cal.dt
FROM cal cal
WHERE cal.dt >= '2016-01-01'
AND cal.dt <= NOW()
AND DATE_FORMAT(cal.dt,'%d') = '01'
) d

MySQL select records for the past 3 months

what will be the smartest way to select all rows from MySQL table for the past 3 months if the table has the following columns:
| id (int) | year (int)| month (int) |
Considering that if the current month & year are for example 2.2016 I need to select all records for 11.2015 & 12.2015 & 1.2016
It is easy if the current month is greater than 3 because all months that I need to select are in the same year so I can subtract 3 from the current month and run simple query
SELECT * FROM mytabe where year=2016 and month >= xx
Select * from mytable where STR_TO_DATE(concat(year,"-",month,"-01"),'%Y-%m-%d')>date_sub(curdate(),Interval 3 month) ;
The above query will get fetch year and month from date 3 months before today
You can select three Months records by these queries follow this.
The columnName means which column data want you select.
The tableName means which table data want you select.
The dateColumnName means which column date base you want to select data.
It would return Last Month data from today.
SELECT columName FROM tableName WHERE dateColumName BETWEEN ( DATE(NOW()) - INTERVAL 1 MONTH) AND Date(Now())
It would return Second Last Month data from today.
SELECT columName FROM tableName WHERE dateColumName BETWEEN ( DATE(NOW()) - INTERVAL 2 MONTH) AND ( DATE(NOW()) - INTERVAL 1 MONTH)
It would return Third Last Month data from today.
SELECT columName FROM tableName WHERE dateColumName BETWEEN ( DATE(NOW()) - INTERVAL 3 MONTH) AND ( DATE(NOW()) - INTERVAL 2 MONTH)
May It help to others.
Please try this
Select * from mytable where STR_TO_DATE(concat(year,"-",month,"-01"),'%Y-%m-%d')>date_sub(curdate(),Interval 3 month) ;

Fetch Previous Week Records from MySql

I have a MySql table having a lot of records. But i want to fetch seperate records of current & previous week.
Query for Current Week Records which works perfectly
SELECT * FROM tbl_track WHERE WEEK(`date_created`) = WEEK(CURDATE())
Query for Previous Week but it dosn't work
SELECT * FROM tbl_track WHERE WEEK(`date_created`) = WEEK(CURDATE()) INTERVAL 7 DAY
SELECT * FROM tbl_track
WHERE WEEK(`date_created`) = WEEK(DATE_SUB(CURDATE(), INTERVAL 7 DAY))
OR:
SELECT * FROM tbl_track
WHERE WEEK(`date_created`) = WEEK(CURDATE() - INTERVAL 7 DAY)
That doesnt look like an index can be used but thats a side issue really. You want your curdate to be - 7 days
SELECT * FROM tbl_track WHERE WEEK(date_created) = WEEK(ADDDATE(CURDATE(), INTERVAL -7 DAY));

Get previous 3 months data based on current date - MySQL

How do I get the previous 3 months data using SQL statement? for example if the current date is 01/01/2012, so how to get the data for December, November, October 2011 ?
Please someone guide me.
SELECT * FROM table1
WHERE mydate BETWEEN DATE_SUB(now(), INTERVAL 3 MONTH) AND now()
Or if you want to stay within the months
SELECT * FROM table1
WHERE MONTH(mydate) BETWEEN MONTH(DATE_SUB(now(), INTERVAL 3 MONTH)) AND MONTH(now())
AND YEAR(mydate) BETWEEN YEAR(DATE_SUB(now(), INTERVAL 3 MONTH)) AND YEAR(now())
This latter version will run much slower, because it cannot use an index for mydate however.