I am storing data in my database. The data being stored looks like this
id | upload_month | created_at
-----------------------------------------
1 | Febuary | 2017-01-30 13:22:39
-----------------------------------------
2 | January | 2017-01-30 13:23:42
-----------------------------------------
3 | January | 2017-01-30 13:25:33
What I needed to do was get the unique upload_months, always using the latest created_at date. So for the above I was after something like this
id | upload_month | created_at
-----------------------------------------
1 | Febuary | 2017-01-30 13:22:39
-----------------------------------------
2 | January | 2017-01-30 13:25:33
-----------------------------------------
To achieve this I have the following SQL
SELECT *
FROM uploaded_file
JOIN (SELECT uploaded_file.upload_month, MAX(uploaded_file.created_at) created_at
FROM uploaded_file
GROUP BY uploaded_file.upload_month) months
ON uploaded_file.upload_month = months.upload_month
AND uploaded_file.created_at = months.created_at
Now the above works well, but now I am looking to order the result of the above by the upload_month. So ideally, the above should have January first and then Febuary.
Is there any way I can order by the upload_month?
Thanks
Assuming all you care about is getting the months in chronological order without regard to the year, then you can format the month as a date, and then sort by that.
For example:
order by str_to_date(concat(year(current_date()),'-', upload_month,'-01'),'%Y-%M-%d')
you can convert month name into number and use it as order by like this.
order by month(str_to_date(upload_month,'%M'))
ORDER BY CASE months.upload_month
WHEN 'January' THEN 1
WHEN 'February' THEN 2
-- ... You get the idea
WHEN 'December' THEN 12
END
And next time you can store month as TINYINT to avoid this problem.
Related
I have the following invoice data :
tbl_invoice :
+------------+--------+
| date | no_inv |
+------------+--------+
| 2021-01-02 | INV1 |
| 2015-01-02 | INV2 |
| 2013-01-01 | INV2 |
| 2021-01-05 | INV4 |
+------------+--------+
I want to display the last 3 months of data available even though it is different for different years, because my expected result is the last 3 months of data.
My Expectation Result :
In the invoice table from this figure, only date data are available in April 2020, May 2019 and June 2015.
I want to get the data for the last 3 months. How can SQL get results according to my expectations?
Assuming your date column is a datetime type, you can do this with a simple where.
You need to calculate the date 3 months ago, and filter to where date is greater than that. e.g.:
WHERE date > DATE_SUB(NOW(), INTERVAL 3 MONTH);
See the datetime arithmetic functions here:
https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html
Solved with :
SELECT date
FROM invoice
GROUP BY MONTH(date)
ORDER BY date DESC
LIMIT 3
I have a table that looks kind of like this;
ID | netID | indate | outdate | name | org
=====================================================================
1 | 50 | 2020-03-31 23:50 | 2020-03-31 23:32 | Bill | orgA
2 | 50 | 2020-03-31 23:51 | 2020-03-31 23:32 | Fred | orgA
3 | 50 | 2020-04-01 00:02 | 2020-04-01 00:05 | Sam | orgA
4 | 51 | 2020-03-31 23:50 | 2020-03-31 23:32 | Harry | orgB
5 | 51 | 2020-03-31 23:51 | 2020-03-31 23:32 | George | orgB
6 | 51 | 2020-04-01 00:02 | 2020-04-01 00:05 | Tom | orgB
I need to write a report by org & year & month, but any row that has the same netID must be included even if it its in a different year or month. And I can't say "WHERE netID = 50" for example because I don't know what netID's are in the month '03' of the year '2020'.
I'm looking for the first three rows to be returned if I need a March 2020 report for orgA.
Below doesn't work for what I need, and I can't figure out how to get all of the rows for each netID regardless of month. Can someone please give me an example of how to retrieve them?
SELECT date(iodate) as logdate,
Name,
netID,
COALESCE( netID, 'Month Total') AS netTTL,
COUNT(ID) AS idCount,
month(logdate AS month
FROM table
WHERE org = 'orgA'
AND year(indate) = '2020'
AND month(iodate) = '03'
GROUP BY year(logdate), month, netID WITH ROLLUP
One method to get all rows where any row exists, that has the same net ID, the requested organization and a date in the requested range is getting the net IDs for the range and organization in a derived table and then join the table.
SELECT t1.*
FROM (SELECT DISTINCT
t2.netid
FROM elbat t2
WHERE t2.org = 'orgA'
AND t2.indate >= '2020-03-01'
AND t2.indate < '2020-04-01') x
INNER JOIN elbat t1
ON t1.netid = x.netid;
A few notes:
You should use range expressions rather than applying year() and month() to the date in the WHERE clause. Range expressions can use indexes and speed up the query.
In your query you have columns/expressions that are neither applied to an aggregation function nor in the GROUP BY. Though older or badly configured MySQL servers accept that, it may produce funny results. But since you didn't further explain what you want to do there, there's not much more to say here than "You're doing it wrong!".
Here is my table:
+--------+---------------------+
| roomNo | date |
+--------+---------------------+
| 1 | 2017-05-17 16:05:00 |
| 1 | 2017-05-17 15:05:00 |
| 2 | 2019-05-20 12:30:00 |
| 2 | 2019-05-15 10:30:00 |
| 2 | 2019-05-14 08:00:00 |
+--------+---------------------+
I want to get the day where the room is used at least once and which day(s) had the most operations in it and how many times, in the current year. I don't know how to compare the dates.
The expected result would be something like :
+--------+------------+------------+
| roomNo | date | operations |
+--------+------------+------------+
| 2 | 2019-05-20 | 3 |
+--------+------------+------------+
We can use MySQL DATE function to lop off times from DATETIME and TIMESTAMP columns. Or we could use MySQL DATE_FORMAT function, to return just year, month day.
We can use an aggregate function like COUNT or SUM in a query with GROUP BY to get counts by room and day.
If "current year" means from Jan 1 thru Dec 31, we can use expression to derive date values of '2019-01-01' and '2020-01-01', and do a comparison of the date column to those values in the WHERE clause.
As a start, consider this:
SELECT t.roomno
, DATE(t.date) AS date_
, COUNT(*) AS cnt_
FROM mytable t
WHERE t.date >= DATE_FORMAT(NOW(),'%Y-01-01') + INTERVAL 0 YEAR
AND t.date < DATE_FORMAT(NOW(),'%Y-01-01') + INTERVAL 1 YEAR
GROUP
BY t.roomno
, DATE(t.date)
ORDER
BY t.roomno
, cnt_ DESC
If the goal is to just return one of the rooms that has the highest number of uses, we could use a LIMIT clause, and order by the highest count to lowest,
ORDER
BY cnt_ DESC
, t.roomno
LIMIT 1
If the results are more complex than that, we can omit the LIMIT clause, and use the result from that query as an inline view in an outer query.
With MySQL 8.0, we can use common table expression (CTE) and window/analytic functions, to get more elaborate results.
I am trying to write a query that tracks the occurrences over a one-month span, with each day of the month being a column of the result. When trying to use group_concat for each day of the month, only the date of the first occurrence is returned. I've included the schemas and data of the 2 tables that I'm working with below, as well as the result that I expect to see and the SQL query that I've tried.
Note: I've simplified the data and schema as much as possible to get to the root of the question.
Tracking
tracking_id | date
_______________________________________
1 | 2017-05-01
2 | 2017-05-02
TrackingStatus
trackingstatus_id | tracking_id | time
___________________________________________
1 | 1 | 09:00
2 | 2 | 10:00
3 | 2 | 14:00
Desired Result
Month | Day1 | Day2
5 | 09:00 | 10:00,14:00
I tried the following query
SELECT
MONTH(date),
if( date = '2017-05-01', group_concat(timeadministered), NULL ),
if( date = '2017-05-02', group_concat(timeadministered), NULL )
FROM trackingstatus ts
JOIN tracking t ON t.tracking_id = ts.tracking_id
GROUP BY MONTH(date)
But am getting the following result
Month | Day1 | Day2
5 | 09:00,10:00,14:00 |
I know that when I use the group by on the date, only the first date value is recognized by the row. Is there a better way to go about this then using group by and group_concat?
You probably want an aggregate function around the expressions in the SELECT list. But wrapping another aggregate around GROUP_CONCAT doesn't make a lot of sense, since the expression in the GROUP BY clause means you will only get back one row for each month.
Maybe you are wanting something like this:
SELECT MONTH(t.date)
, GROUP_CONCAT(IF(t.date = '2017-05-01',t.timeadministered,NULL)) AS Day01
, GROUP_CONCAT(IF(t.date = '2017-05-02',t.timeadministered,NULL)) AS Day02
FROM ...
GROUP BY MONTH(t.date)
How do I generate the following reports using MYSQL?
My table 'reservations' looks like this:
id | arrival | created.
1 | 2014-3-30 | 2014-3-1
2 | 2014-3-31 | 2014-3-2
3 | 2014-3-28 | 2014-3-2
4 | 2014-3-01 | 2014-3-1
5 | 2014-3-01 | 2014-3-1
I want to generate the following two aggregation reports for the "arrival" column for the whole month as shown below:
(1)
arrival | count | total_monthly_arrivals
2014-03-01 | 2 | 5
2014-03-02 | 0 | 5
2014-03-03 | 0 | 5
...
2014-03-30 | 1 | 5
2014-03-31 | 1 | 5
(2)
January | 5
...
March | 5
...
December | 0 | 5
I want these 2 result sets. It generates date according & month according report and generate result set in these form.
I tried to use group by with count in first resultset but it doesn't retrieve for a date that does not exist. Again I wanna put month condition such that I choose month. where month = '02' or something like this. Is that possible?
My SQLFiddle should answer both parts of your question: http://sqlfiddle.com/#!2/9f130/31
This will return the arrival date with a count of how many people are coming that day and how many monthly arrivals there are
select distinct(r.arrival) as arrival_date,
count(r.arrival) as total_per_day,
sa.month_total as total_arrival_per_month
from reservations as r
,(select substr(arrival,6,2) as month,
count(substr(arrival,6,2)) as month_total
from reservations
group by month) as sa
where substr(r.arrival,6,2) = sa.month
group by arrival_date,total_arrival_per_month;
This will return the month of the year and how many people are booked for that month and how many are arriving that month. (Updated with the suggestion from agrizzo.)
select MONTHNAME(STR_TO_DATE(substr(r.arrival,6,2), '%m')) as arrival_date,
sa.month_total as total_arrival_per_month
from reservations as r
,(select substr(arrival,6,2) as month,
count(substr(arrival,6,2)) as month_total
from reservations
group by month) as sa
where substr(r.arrival,6,2) = sa.month
group by arrival_date,total_arrival_per_month;
There is however, no way for me to give you every day/month of the year without a fully qualified data set, provided by and prefilled by you. That's on you to do and provide us with.
However, you can check this thread. Get a list of dates between two dates and leverage their information with my queries to get your desired results.