How to find data from last week in MySQL - mysql

I want to display data from
Q1: only last week of each student.
Q2: only last month of each student.
How can I achieve this?
DEMO for week
DEMO for month
CREATE TABLE `hw_homework` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`studentid` int(10) NOT NULL,
`subjectid` int(10) NOT NULL,
`assignment_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`teacherid` int(10) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ;
INSERT INTO `hw_homework` (`id`, `studentid`, `subjectid`, `assignment_name`, `teacherid`,
`date`) VALUES
(1, 29, 5, '5E', 20, '2012-11-04 13:58:40'),
(2, 15, 5, '32B', 20, '2012-11-04 13:59:54'),
(3, 29, 4, 'Q2A', 20, '2012-10-30 17:53:46'),
(4, 29, 11, '6E', 20, '2012-11-02 20:06:39'),
(5, 29, 11, 'C15', 20, '2012-10-16 20:06:30'),
(6, 15, 11, '7A', 20, '2012-09-19 20:08:05'),
(7, 29, 5, '3B', 20, '2012-09-14 20:08:12'),
(8, 29, 13, '6E', 32, '2012-10-29 20:23:46'),
(9, 29, 11, '7E', 18, '2012-10-30 14:35:14'),
(10, 2, 5, '5E', 20, '2012-10-21 13:58:40'),
(11, 2, 5, '5E', 20, '2012-10-30 13:58:40'),
(12, 2, 5, '5E', 20, '2012-10-31 13:58:40');
This does not work for last week. It shows this week result.
SELECT studentID,
DATE_FORMAT(`date`, '%U') `WeekNo`,
COUNT(studentID) totalMissed
FROM hw_homework he
WHERE DATE_FORMAT(`date`, '%U') = (SELECT MAX(DATE_FORMAT(NOW(), '%U')) FROM hw_homework hi WHERE hi.studentID = he.studentID)
-- AND studentID = ''
GROUP BY studentID, DATE_FORMAT(`date`, '%U')
This does not work for last month. This shows this month result.
SELECT studentID,
DATE_FORMAT(`date`, '%M') `Month`,
COUNT(studentID) totalMissed
FROM hw_homework he
WHERE DATE_FORMAT(`date`, '%M') = (SELECT MAX(DATE_FORMAT(NOW(), '%M')) FROM hw_homework hi WHERE hi.studentID = he.studentID)
-- AND studentID = ''
GROUP BY studentID, DATE_FORMAT(`date`, '%M')
Thanks in advance.

try subtracting 1 from weekNo:
SELECT studentID,
DATE_FORMAT(`date`, '%U') `WeekNo`,
COUNT(studentID) totalMissed
FROM hw_homework he
WHERE DATE_FORMAT(`date`, '%U') =
(SELECT MAX(DATE_FORMAT(NOW(), '%U')-1)
FROM hw_homework hi
WHERE hi.studentID = he.studentID)
GROUP BY studentID, DATE_FORMAT(`date`, '%U')

Related

MYSQL 5.6 get latest data of each user

My Database table is as shown below. I need to get latest mark of each student. Latest entry is the row with maximum udate and maximum oder. (The oder will be incremented by one on each entry with same date)
In my example, I have two students Mujeeb, Zakariya and two subjects ENGLISH, MATHS. I need to get latest mark of each student for each subject. My expectd result is as follows
My sample data is
DROP TABLE IF EXISTS `students`;
CREATE TABLE IF NOT EXISTS `students` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`udate` date NOT NULL,
`oder` int(11) NOT NULL,
`name` varchar(20) NOT NULL,
`Subject` varchar(20) NOT NULL,
`mark` int(11) NOT NULL,
PRIMARY KEY (`uid`)
) ENGINE=MyISAM AUTO_INCREMENT=13 DEFAULT CHARSET=latin1;
INSERT INTO `students` (`uid`, `udate`, `oder`, `name`, `Subject`, `mark`) VALUES
(1, '2021-08-01', 1, 'Mujeeb', 'ENGLISH', 10),
(2, '2021-08-01', 1, 'Zakariya', 'ENGLISH', 20),
(3, '2021-08-10', 2, 'Mujeeb', 'ENGLISH', 50),
(4, '2021-08-11', 2, 'Zakariya', 'ENGLISH', 60),
(5, '2021-08-02', 1, 'Mujeeb', 'ENGLISH', 100),
(6, '2021-08-03', 1, 'Zakariya', 'ENGLISH', 110),
(7, '2021-08-10', 1, 'Mujeeb', 'ENGLISH', 500),
(8, '2021-08-11', 1, 'Zakariya', 'ENGLISH', 600),
(9, '2021-08-01', 2, 'Mujeeb', 'MATHS', 100),
(10, '2021-08-01', 2, 'Zakariya', 'MATHS', 75),
(11, '2021-08-10', 3, 'Mujeeb', 'MATHS', 50),
(12, '2021-08-11', 3, 'Zakariya', 'MATHS', 60);
Use NOT EXISTS:
SELECT s1.*
FROM students s1
WHERE NOT EXISTS (
SELECT 1
FROM students s2
WHERE s2.name = s1.name AND s2.Subject = s1.Subject
AND (s2.udate > s1.udate OR (s2.udate = s1.udate AND s2.oder > s1.oder))
);
Or with a correlated subquery in the WHERE clause:
SELECT s1.*
FROM students s1
WHERE s1.uid = (
SELECT s2.uid
FROM students s2
WHERE s2.name = s1.name AND s2.Subject = s1.Subject
ORDER BY s2.udate DESC, s2.oder DESC LIMIT 1
);
See the demo.
As ROW_NUMBER() function doesn't work at lower version of MySQL, So alternate way of row_number() is used for this solution.
-- MySQL (v5.6)
SELECT p.uid, p.udate, p.oder, p.name, p.Subject, p.mark
FROM (SELECT #row_no := IF((#prev_val = t.name && #prev_val1 = t.Subject), #row_no + 1, 1) AS row_number
, #prev_val := t.name AS name
, #prev_val1 := t.Subject AS Subject
, t.mark
, t.oder
, t.uid
, t.udate
FROM students t,
(SELECT #row_no := 0) x,
(SELECT #prev_val := '') y,
(SELECT #prev_val1 := '') z
ORDER BY t.name, t.Subject, t.udate DESC, t.oder DESC ) p
WHERE p.row_number = 1
ORDER BY p.name, p.Subject;
Please check the url http://sqlfiddle.com/#!9/b5befe/18

How do I build a query to get the latest row per user where a third criteria is in a separate table?

I have three tables
CREATE TABLE `LineItems` (
`LineItemID` int NOT NULL,
`OrderID` int NOT NULL,
`ProductID` int NOT NULL
);
INSERT INTO `LineItems` (`LineItemID`, `OrderID`, `ProductID`) VALUES
(1, 1, 2),
(2, 1, 1),
(3, 2, 3),
(4, 2, 4),
(5, 3, 1),
(6, 4, 2),
(7, 5, 4),
(8, 5, 2),
(9, 5, 3),
(10, 6, 1),
(11, 6, 4),
(12, 7, 4),
(13, 7, 1),
(14, 7, 2),
(15, 8, 1),
(16, 9, 3),
(17, 9, 4),
(18, 10, 3);
CREATE TABLE `Orders` (
`OrderID` int NOT NULL,
`UserID` int NOT NULL,
`OrderDate` datetime NOT NULL
);
INSERT INTO `Orders` (`OrderID`, `UserID`, `OrderDate`) VALUES
(1, 21, '2021-05-01 00:00:00'),
(2, 21, '2021-05-03 00:00:00'),
(3, 24, '2021-05-06 00:00:00'),
(4, 23, '2021-05-12 00:00:00'),
(5, 21, '2021-05-14 00:00:00'),
(6, 22, '2021-05-16 00:00:00'),
(7, 23, '2021-05-20 00:00:00'),
(8, 21, '2021-05-22 00:00:00'),
(9, 24, '2021-05-23 00:00:00'),
(10, 23, '2021-05-26 00:00:00');
CREATE TABLE `Products` (
`ProductID` int NOT NULL,
`ProductTitle` VARCHAR(250) NOT NULL,
`ProductType` enum('doors','windows','flooring') NOT NULL
);
INSERT INTO `Products` (`ProductID`, `ProductTitle`, `ProductType`) VALUES
(1, 'French Doors','doors'),
(2, 'Sash Windows','windows'),
(3, 'Sliding Doors','doors'),
(4, 'Parquet Floor','flooring');
SQL Fiddle:
Orders - contains an order date and a user id
LineItems - Foreign key to the orders table, contains product ids that are in the order
Products - Contains details of the products (including if they are a door, window, or flooring)
I have figured out how to get the latest order per user with
SELECT O.* FROM Orders O LEFT JOIN Orders O2
ON O2.UserID=O.UserID AND O.OrderDate < O2.OrderDate
WHERE O2.OrderDate IS NULL;
This works fine and is included in the SQL fiddle, along with a query that returns a complete picture for reference.
I am trying to figure out how to get the latest order with flooring per user, but I'm not having any luck.
In the SQL fiddle linked above, the intended output for what I am after would be
OrderID | UserID | OrderDate
6 | 22 | 2021-05-16T00:00:00Z
5 | 21 | 2021-05-14T00:00:00Z
9 | 24 | 2021-05-23T00:00:00Z
7 | 23 | 2021-05-20T00:00:00Z
EDIT: To clarify, in the intended result, two rows (for users 21 and 23) are different than in the query that gets just latest order per user. This is because order IDs 8 and 10 (from the latest order per user query) do not include flooring. The intended query has to find the latest order with flooring from each user to return in the result set.
You need to add the LineItems and Products tables to your query to find orders where flooring was purchased:
SELECT DISTINCT O.*
FROM Orders O
LEFT JOIN Orders O2
ON O2.UserID=O.UserID AND
O.OrderDate < O2.OrderDate
INNER JOIN LineItems i
ON i.OrderID = O.OrderID
INNER JOIN Products p
ON p.ProductID = i.ProductID
WHERE O2.OrderDate IS NULL AND
p.ProductType = 'flooring'
db<>fiddle here

how can I avoid column which contain null or zero value [duplicate]

This question already has an answer here:
Can you help to modify the query or other query for getting the expected result
(1 answer)
Closed 5 years ago.
I want to avoid those column which contain null or zero value
here the table structure
-- Table structure for table orders
CREATE TABLE `orders` (
`id` int(11) NOT NULL,
`customer_id` int(11) NOT NULL,
`restaurant_id` int(11) NOT NULL,
`source_id` int(1) NOT NULL,
`purchase_method` varchar(255) NOT NULL,
`total_price` int(11) NOT NULL,
`date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `orders`
--
INSERT INTO `orders` (`id`, `customer_id`, `restaurant_id`, `source_id`, `purchase_method`, `total_price`, `date_created`) VALUES
(1, 1, 1, 3, 'Cash', 500, '2016-05-31 11:44:16'),
(2, 1, 1, 3, 'Cash', 1500, '2016-06-01 11:44:22'),
(3, 1, 1, 3, '', 650, '2016-06-02 11:44:26'),
(4, 1, 1, 2, 'cash', 1500, '2016-06-03 11:44:31'),
(5, 1, 1, 1, 'cash', 12000, '2016-06-04 21:08:00'),
(6, 1, 1, 1, 'cash', 14500, '2016-06-05 00:00:00'),
(7, 1, 1, 2, 'cash', 15000, '2016-06-10 09:47:15'),
(8, 1, 1, 2, 'cash', 14500, '2016-05-10 10:03:55'),
(9, 1, 1, 1, 'cash', 11800, '2016-06-08 00:00:00'),
(10, 1, 1, 2, 'ss', 300, '2016-06-08 01:06:56'),
(11, 1, 1, 1, 'online', 400, '2016-05-10 10:03:20'),
(12, 1, 1, 3, 'cash', 5000, '2016-06-09 06:23:16'),
(13, 1, 1, 2, 'cash', 2000, '2016-05-10 10:03:35'),
(14, 1, 1, 1, 'cash', 499, '2016-04-11 18:30:00'),
(15, 1, 1, 1, 'cash', 2010, '2016-03-11 18:58:00'),
(16, 1, 1, 1, 'cash', 599, '2016-03-11 18:30:00'),
(17, 1, 1, 1, 'online', 699, '2016-05-02 18:30:00');
-- --------------------------------------------------------
the query I tried below it
SELECT
SUM(CASE WHEN MONTH(date_created)=1 THEN (total_price) END) Jan,
SUM(CASE WHEN MONTH(date_created)=2 THEN (total_price) END) Feb,
SUM(CASE WHEN MONTH(date_created)=3 THEN (total_price) END) Mar,
SUM(CASE WHEN MONTH(date_created)=4 THEN (total_price) END) Apr,
SUM(CASE WHEN MONTH(date_created)=5 THEN (total_price) END) May,
SUM(CASE WHEN MONTH(date_created)=6 THEN (total_price) END) Jun,
SUM(CASE WHEN MONTH(date_created)=7 THEN (total_price) END) July,
SUM(CASE WHEN MONTH(date_created)=8 THEN (total_price) END) Aug,
SUM(CASE WHEN MONTH(date_created)=9 THEN (total_price) END) Sep,
SUM(CASE WHEN MONTH(date_created)=10 THEN (total_price) END) 'Oct',
SUM(CASE WHEN MONTH(date_created)=11 THEN (total_price) END) Nov,
SUM(CASE WHEN MONTH(date_created)=12 THEN (total_price) END) 'Dec'
FROM orders
WHERE source_id =1 AND date_created BETWEEN(CURDATE() - INTERVAL 1 MONTH)
AND CURDATE()
Result I get from query
Jan Feb Mar Apr May Jun July Aug Sep Oct Nov Dec
null null null null null 38300 null null null null null null null
desire result
may june
0 38300
A SQL query returns a fixed set of columns, determined by the from clause. If you want a variable set of columns, then you can use dynamic SQL.
In your case, perhaps getting the results as columns would suffice:
select month(date_created), sum(total_price)
from orders
where source_id = 1 and
date_created BETWEEN(CURDATE() - INTERVAL 1 MONTH) and CURDATE()
group by month(date_created)
having sum(total_price) <> 0;

Select and show business open hours from MySQL

I dont need to check if business is open or close, but I need to show open hours by days.
There are some options:
1 - Business open once in day (sample - from 10:00 to 18:30) - one
rows in table
2 - Business open TWICE in day (samlpe - from 10:00 to
14:00 and from 15:00 to 18:30) - two rows in table
3 - Business may
be closed (no row inserted)
Here my MySql table of hours storing. In this sample business (affiliate_id) are open twice in days from 0 to 4, once in day 5 and closed in day 6 (no records for this day)
http://postimage.org/image/yplj4rumj/
What I need to show in website its like (according to this database example:
0,1,2,3,4 - open 10:00-14:00 and 15:00-18:30
5 - open 10:00-12:00
6 - closed
How I get results like:
http://postimage.org/image/toe53en63/
?
I tried to make queries with GROUPֹ_CONCAT and LEFT JOIN the same table ON a.day=b.day but with no luck :(
There sample of my query (that is wrong)
SELECT GROUP_CONCAT( DISTINCT CAST( a.day AS CHAR )
ORDER BY a.day ) AS days, DATE_FORMAT( a.time_from, '%H:%i' ) AS f_time_from, DATE_FORMAT( a.time_to, '%H:%i' ) AS f_time_to, DATE_FORMAT( b.time_from, '%H:%i' ) AS f_time_from_s, DATE_FORMAT( b.time_to, '%H:%i' ) AS f_time_to_s
FROM business_affiliate_hours AS a LEFT
JOIN business_affiliate_hours AS b ON a.day = b.day
WHERE a.affiliate_id =57
GROUP BY a.time_from, a.time_to, b.time_from, b.time_to
ORDER BY a.id ASC
This my table:
CREATE TABLE IF NOT EXISTS `business_affiliate_hours` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`affiliate_id` int(10) unsigned NOT NULL DEFAULT '0',
`time_from` time NOT NULL,
`time_to` time NOT NULL,
`day` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
INSERT INTO `business_affiliate_hours` (`id`, `affiliate_id`, `time_from`, `time_to`, `day`) VALUES
(53, 57, '10:00:00', '12:00:00', 5),
(52, 57, '15:00:00', '18:30:00', 4),
(51, 57, '10:00:00', '14:00:00', 4),
(50, 57, '15:00:00', '18:30:00', 3),
(49, 57, '10:00:00', '14:00:00', 3),
(48, 57, '15:00:00', '18:30:00', 2),
(47, 57, '10:00:00', '14:00:00', 2),
(46, 57, '15:00:00', '18:30:00', 1),
(45, 57, '10:00:00', '14:00:00', 1),
(44, 57, '15:00:00', '18:30:00', 0),
(43, 57, '10:00:00', '14:00:00', 0);
Open hours may be different for every day, so I want to GROUP by the same open hours, and get list of days for all unique order of open hours.
Need your help!
Sorry for links to images, I cant upload images yes to here.
First build a materialised table of each day's combined times, then group on that:
SELECT GROUP_CONCAT(day ORDER BY day) AS days,
DATE_FORMAT(f1, '%H:%i') AS f_time_from,
DATE_FORMAT(t1, '%H:%i') AS f_time_to,
DATE_FORMAT(f2, '%H:%i') AS f_time_from_s,
DATE_FORMAT(t2, '%H:%i') AS f_time_to_s
FROM (
SELECT day,
MIN(time_from) AS f1,
MIN(time_to ) AS t1,
IF(COUNT(*) > 1, MAX(time_from), NULL) AS f2,
IF(COUNT(*) > 1, MAX(time_to ), NULL) AS t2
FROM business_affiliate_hours
WHERE affiliate_id = 57
GROUP BY day
) t
GROUP BY f1, t1, f2, t2
ORDER BY days
See it on sqlfiddle.

How to find the latest week and month from MySQL

This DEMO shows by month. And this DEMO shows by week. However I want to display
Q1: only this week of each student.
Q2: only this month of each student.
Q3: only last week of each student.
Q4: only last month of each student.
How can I achieve this?
CREATE TABLE `hw_homework` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`studentid` int(10) NOT NULL,
`subjectid` int(10) NOT NULL,
`assignment_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`teacherid` int(10) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ;
INSERT INTO `hw_homework` (`id`, `studentid`, `subjectid`, `assignment_name`, `teacherid`, `date`) VALUES
(1, 29, 5, '5E', 20, '2012-10-31 13:58:40'),
(2, 15, 5, '32B', 20, '2012-10-31 13:59:54'),
(3, 29, 4, 'Q2A', 20, '2012-10-30 17:53:46'),
(4, 29, 11, '6E', 20, '2012-10-02 20:06:39'),
(5, 29, 11, 'C15', 20, '2012-10-16 20:06:30'),
(6, 15, 11, '7A', 20, '2012-09-19 20:08:05'),
(7, 29, 5, '3B', 20, '2012-09-14 20:08:12'),
(8, 29, 13, '6E', 32, '2012-10-29 20:23:46'),
(9, 29, 11, '7E', 18, '2012-10-30 14:35:14'),
(10, 2, 5, '5E', 20, '2012-10-21 13:58:40'),
(11, 2, 5, '5E', 20, '2012-10-30 13:58:40'),
(12, 2, 5, '5E', 20, '2012-10-31 13:58:40');
By month
SELECT studentID,
DATE_FORMAT(`date`, '%M') `month`,
COUNT(studentID) totalMissed
FROM hw_homework
-- WHERE studentID = ''
GROUP BY studentID, DATE_FORMAT(`date`, '%M')
By week
SELECT studentID,
DATE_FORMAT(`date`, '%U') `WeekNo`,
COUNT(studentID) totalMissed
FROM hw_homework
-- WHERE studentID = ''
GROUP BY studentID, DATE_FORMAT(`date`, '%U')
Thanks in advance.
A1 :
SELECT studentID,
DATE_FORMAT(`date`, '%U') `WeekNo`,
COUNT(studentID) totalMissed
FROM hw_homework
WHERE DATE_FORMAT(`date`, '%U') = DATE_FORMAT(NOW(), '%U')
-- AND studentID = ''
GROUP BY studentID, DATE_FORMAT(`date`, '%U')
A2 :
SELECT studentID,
DATE_FORMAT(`date`, '%M') `WeekNo`,
COUNT(studentID) totalMissed
FROM hw_homework
WHERE DATE_FORMAT(`date`, '%M') = DATE_FORMAT(NOW(), '%M')
-- AND studentID = ''
GROUP BY studentID, DATE_FORMAT(`date`, '%M')
A3 :
SELECT studentID,
DATE_FORMAT(`date`, '%U') `WeekNo`,
COUNT(studentID) totalMissed
FROM hw_homework he
WHERE DATE_FORMAT(`date`, '%U') = (SELECT MAX(DATE_FORMAT(NOW(), '%U')) FROM hw_homework hi WHERE hi.studentID = he.studentID)
-- AND studentID = ''
GROUP BY studentID, DATE_FORMAT(`date`, '%U')
A4 :
SELECT studentID,
DATE_FORMAT(`date`, '%M') `WeekNo`,
COUNT(studentID) totalMissed
FROM hw_homework he
WHERE DATE_FORMAT(`date`, '%M') = (SELECT MAX(DATE_FORMAT(NOW(), '%M')) FROM hw_homework hi WHERE hi.studentID = he.studentID)
-- AND studentID = ''
GROUP BY studentID, DATE_FORMAT(`date`, '%M')