Hi I want a SQL statement that would return all courses
having at least 2 students enrolled which is ordered by course with the
greatest number of students. I am pretty new with SQL stuff and I am finding it bit difficult.
here is my current database
CREATE TABLE `course` (
`CourseID` char(11) NOT NULL,
`Course_name` varchar(22) DEFAULT NULL,
`hours_per_week` varchar(22) DEFAULT NULL,
`Start_date` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `course`
--
INSERT INTO `course` (`CourseID`, `Course_name`, `hours_per_week`, `Start_date`) VALUES
('C001', 'Cert 1', '15', '2012-02-01'),
('C002', 'Cert 2', '20', '2012-02-02'),
('C003', 'Cert 3', '16', '2012-02-03'),
('C004', 'Cert 4', '20', '2012-02-13');
-- --------------------------------------------------------
--
-- Table structure for table `enrolment`
--
CREATE TABLE `enrolment` (
`studentID` char(11) NOT NULL,
`courseID` char(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `enrolment`
--
INSERT INTO `enrolment` (`studentID`, `courseID`) VALUES
('S001', 'C001'),
('S002', ' C001'),
('S003', ' C002'),
('S004', ' C002'),
('S005', ' C004');
-- --------------------------------------------------------
--
-- Table structure for table `student`
--
CREATE TABLE `student` (
`StudentID` char(11) NOT NULL,
`FirstName` varchar(22) DEFAULT NULL,
`LastName` varchar(22) DEFAULT NULL,
`DOB` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `student`
--
INSERT INTO `student` (`StudentID`, `FirstName`, `LastName`, `DOB`) VALUES
('S001', 'Alison', 'Tildesley', '1984-05-09'),
('S002', 'Fred', 'Nile', '1940-03-03'),
('S003', 'Christine', 'Anu', '1970-09-01'),
('S004', 'Jame', 'Brown', '1976-02-03'),
('S005', 'Mark', 'Oliphant', '1958-03-10'),
('S006', 'George', 'Bush', '1951-11-28');
This is what I have tried
SELECT FROM COURSES WHERE STUDENT_ID >=2
I know I have to add student_id row into my course table but I am still confused how to get desired results. I am sorry I am very new to database and MYSQL statements.
This should do:
SELECT C.CourseID, C.Course_name, COUNT(E.StudentID) Students_num
FROM course C
JOIN enrolment E USING(CourseID)
GROUP BY C.CourseID, C.Course_name
HAVING Students_num >= 2
ORDER BY Students_num DESC, C.Course_name
This will extract all courses joined with their enrollment records, and then group them by the course ID and name, counting the number of students; the last HAVING clause will discard all records that, after the grouping, will have less than 2 students.
Here is a working SQL fiddle for testing.
Not tested ;)
select
c.courseID, count(0)
from course c, enrolment e
where c.CourseID = e.CourseID
group by
c.courseID
having
count(0) >= 2
order by
count(0) desc
Related
Suppose the schemas are
users(id, name)
users_attributes(user_id, attribute_name, attribute_value)
Sample data:
--
-- Database: `sample_db`
--
CREATE DATABASE IF NOT EXISTS `sample_db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE `sample_db`;
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`id`, `name`) VALUES
(1, 'Tim'),
(2, 'Joe'),
(3, 'Bob');
-- --------------------------------------------------------
--
-- Table structure for table `users_attributes`
--
CREATE TABLE `users_attributes` (
`user_id` int(11) NOT NULL,
`attribute_name` varchar(50) NOT NULL,
`attribute_value` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Dumping data for table `users_attributes`
--
INSERT INTO `users_attributes` (`user_id`, `attribute_name`, `attribute_value`) VALUES
(1, 'height', '10'),
(1, 'over_18', 'yes'),
(2, 'height', '5'),
(3, 'height', '7');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `users_attributes`
--
ALTER TABLE `users_attributes`
ADD UNIQUE KEY `user_id` (`user_id`,`attribute_name`,`attribute_value`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
COMMIT;
Right now I'm calling INNER JOIN on a specific attribute_name so my selection also returns that along with the user id and name. Now I want to exclude from whatever I selected, if they contain a certain other attribute. I know I can accomplish that by using a NOT IN (SELECT ...) conditional but can I do that without having to select again?
EDIT:
Attributes may or may not exist for all users. For example, I would like to fetch id, name, attribute_value where attribute_name = height but only if attribute_name over_18 does not exist or is 'no'
want to join tables
i have five tables like this
Table-1 named as software
CREATE TABLE IF NOT EXISTS `software` (
`software_name` varchar(50) NOT NULL,
`software_version` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `software` (`software_name`, `software_version`) VALUES
('freemap', '1.0'),
('freegps', '1.2');
Table-2 named as cms
CREATE TABLE IF NOT EXISTS `cms` (
`cms_name` varchar(50) NOT NULL,
`cms_product` varchar(50) NOT NULL,
`cms_version` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `cms` (`cms_name`, `cms_product`, `cms_version`) VALUES
('org:freemap:1.0', 'freemap', '1.0'),
('org:freegps:1.0', 'freegps', '1.2');
Table-3 named as cms_to_sve
CREATE TABLE IF NOT EXISTS `cms_to_sve` (
`cms_id` varchar(50) NOT NULL,
`sw_vul_id` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `cms_to_sve` (`cms_id`, `sw_vul_id`) VALUES
('org:freemap:1.0', '423'),
('org:freemap:1.0', '424'),
('org:freemap:1.0', '425'),
('org:freemap:1.0', '426'),
('org:freegps:1.2', '940'),
('org:freegps:1.2', '941');
Table-4 named as software_details
CREATE TABLE IF NOT EXISTS `software_details` (
`sw_id` varchar(50) NOT NULL,
`sve_id` varchar(50) NOT NULL,
`score` varchar(50) NOT NULL,
`ratio` varchar(50) NOT NULL,
`swe_id` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `software_details` (`sw_id`, `sve_id`, `score`, `ratio`, `swe_id`) VALUES
('423', '2001-1991', '5', 'high', '320'),
('424', '2004-1996', '7.5', 'medium', '460'),
('425', '2008-9001', '8', 'low', '122'),
('426', '2012-0002', '4', 'high', '128'),
('940', '2003-1993', '6', 'medium', '424'),
('941', '2006-1994', '3', 'high', '112');
Table-5 named as swe
CREATE TABLE IF NOT EXISTS `swe` (
`swe_name` varchar(50) NOT NULL,
`swe_id` varchar(50) NOT NULL,
`swe_des` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `swe` (`swe_name`, `swe_id`, `swe_des`) VALUES
('ref software', '320', 'hello'),
('ref complicated', '480', 'hi welcome'),
('ref contact', '122', 'how are you'),
('ref admire', '123', 'who is that'),
('ref super', '424', 'well join us'),
('ref nice', '112', 'cheers');
i want to join these five tables
i have few hints
need to compare table 1 and table 2 (that is table
software and table cms)
compare software_name with cms_product and
software_version with cms_version
these should relate with cms_name
with second table column cms_name has to join with the third
table common column cms_id
where in third table cms_id must be equal to sw_vul_id
then join fourth table
now join fourth table from third table using sw_vul_id is equal
to sw_id and get the remaining column values
join fifth table and fourth table by swe-id and get the other
column values
finally i want to have an output like this
i need query for this .
Just like PeteCon said in his comment , left join can be used, hope this will help.
select tbl1.software_name, tbl1.software_version, tbl4.sve_id, tbl4.score, tbl4.ratio, tbl5.swe_id, tbl5.swe_name, tbl5.swe_des
from software tbl1
left join cms tbl2 on tbl1.software_name = tbl2.cms_product and tbl1.software_version = tbl2.cms_version
left join cms_to_sve tbl3 on tbl2.cms_name = tbl3.cms_id
left join software_details tbl4 on tbl3.sw_vul_id = tbl4.sw_id
left join swe tbl5 on tbl4.swe_id = tbl5.swe_id
http://sqlfiddle.com/#!9/3735e7/1
I think some of your sample data is not sufficient to get the result that you want, but in your real database the query should give you something like you want.
I need a joined (Union like) result from multiple databases on the same databaseserver in one query. Every customer database contains a location table and all customers are listed in the core database.
I don't need a simple join between to different databases. I need the actual joined database name to come from the same query.
I figure something like this.
SELECT customerlist.dbname,customerlist.realname,location.address
FROM core.customerlist
INNER JOIN `customer.dbname`.location
ORDER BY customerlist.realname
I know this won't work, I'm just trying to pseudo code what I'm searching for. I hope someone can help.
Database structure:
-- Database: `core`
CREATE TABLE IF NOT EXISTS `customerlist` (
`realname` varchar(20) NOT NULL,
`dbname` varchar(16) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `customerlist` (`realname`, `dbname`) VALUES
('Johnny', 'johnny'),
('Alfred', 'alfred');
-- --------------------------------------------------------
-- Database: `alfred`
CREATE TABLE IF NOT EXISTS `location` (
`address` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `location` (`address`) VALUES
('House Three'),
('Car 1');
-- --------------------------------------------------------
-- Database: `johnny`
CREATE TABLE IF NOT EXISTS `location` (
`address` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `location` (`address`) VALUES
('House One'),
('House Two');
Desired result;
johnny,Johnny,House One
johnny,Johnny,House Two
alfred,Alfred,House Three
alfred,Alfred,Car 1
You'll have to be careful of the two table identical tables...joining them in a union if fine since they are identical in structure:
SELECT customerlist.dbname,customerlist.realname,location.address
FROM core.customerlist
LEFT JOIN (
SELECT * FROM (johnny.location UNION alfred.location
)) AS T2 ON customerlist.dbname = T2.dbname
ORDER BY customerlist.realname
_
Hello everyone!
I have table
CREATE TABLE `labels` (
`id` INT NULL AUTO_INCREMENT DEFAULT NULL,
`name` VARCHAR(250) NULL DEFAULT NULL,
`score` INT NULL DEFAULT NULL,
`before_score` INT NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
And I Have This Table
CREATE TABLE `scores` (
`id` INT NULL AUTO_INCREMENT DEFAULT NULL,
`name_id` INT NULL DEFAULT NULL,
`score` INT NULL DEFAULT NULL,
`date` DATETIME DEFAULT NULL,
PRIMARY KEY (`id`)
);
And i want have result where labels.score - have value last scores.score sorted by scores.date and labels.before_score where have value penultimate scores.score sorted by scores.date. Can I do This Only on Mysql slq and how?
Thanks.
ADD
For example i have this data on first table:
INSERT INTO `labels` (id, name, score, before_score) VALUES (1, 'John', 200, 123);
INSERT INTO `labels` (id, name, score, before_score) VALUES (2, 'Eddie', 2000, 2000);
INSERT INTO `labels` (id, name, score, before_score) VALUES (3, 'Bob', 400, 3101);
And second table
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('1','1','12','2013-07-10');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('2','2','2000','2013-05-04');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('3','3','654','2012-09-12');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('4','1','123','2013-12-17');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('5','1','200','2014-04-25');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('6','3','3101','2013-12-02');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('6','2','2000','2015-12-02');
INSERT INTO `scores` (`id`,`name_id`,`score`,`date`) VALUES ('6','3','400','2013-12-02');
If I understand correctly, you need the last two scores for each name_id.
I would tackle this with temporary tables:
Step 1. Last score:
create temporary table temp_score1
select name_id, max(`date`) as lastDate
from scores
group by name_id;
-- Add the appropriate indexes
alter table temp_score1
add unique index idx_name_id(name_id),
add index idx_lastDate(lastDate);
Step 2. Penultimate score. The idea is exactly the same, but using temp_score1 to filter the data:
create temporary table temp_score2
select s.name_id, max(`date`) as penultimateDate
from scores as s
inner join temp_score1 as t on s.nameId = t.nameId
where s.`date` < t.lastDate
group by name_id;
-- Add the appropriate indexes
alter table temp_score2
add unique index idx_name_id(name_id),
add index idx_penultimateDate(penultimateDate);
Step 3. Put it all together.
select
l.id, l.name,
s1.lastScore, s2.penultimateScore
from
`labels` as l
left join temp_score1 as s1 on l.id = s1.name_id
left join temp_score2 as s2 on l.id = s2.name_id
You can put this three steps inside a stored procedure.
Hope this helps you.
I have three tables:
"products" - contains products
"location" - store location
"product_orders" - joins data from products and location
SQL DUMP:
--
-- Table structure for table `location`
--
CREATE TABLE IF NOT EXISTS `location` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=77 ;
--
-- Dumping data for table `location`
--
INSERT INTO `location` (`id`, `name`) VALUES
(1, 'Miami'),
(2, 'Denver');
-- --------------------------------------------------------
--
-- Table structure for table `products`
--
CREATE TABLE IF NOT EXISTS `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(255) NOT NULL DEFAULT '',
`product` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=6014552 ;
--
-- Dumping data for table `products`
--
INSERT INTO `products` (`id`, `type`, `product`) VALUES
(1, 'shirt', 'red shirt'),
(2, 'shirt', 'red shirt'),
(3, 'pants', 'blue pants'),
(4, 'pants', 'blue pants');
-- --------------------------------------------------------
--
-- Table structure for table `product_orders`
--
CREATE TABLE IF NOT EXISTS `product_orders` (
`product_id` int(11) NOT NULL,
`location_id` int(11) NOT NULL,
`status` varchar(255) NOT NULL,
PRIMARY KEY (`product_id`,`location_id`),
KEY `ix_product_orders` (`location_id`),
KEY `ix_product_orders_1` (`product_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
--
-- Dumping data for table `product_orders`
--
INSERT INTO `product_orders` (`product_id`, `location_id`, `status`) VALUES
(1, 1, 'sold'),
(2, 2, 'sold'),
(1, 2, 'available'),
(2, 1, 'sold');
If I want to select all sold products from store 'miami - this query works:
SELECT * FROM `products`
INNER JOIN `product_orders`
ON `product_orders`.`product_id`= `products`.`id`
WHERE `product_orders`.`location_id` = '1'
AND
status = 'sold'
How would you rewrite to delete all sold products from the miami store? My query is not working:
DELETE `products` FROM `products`
INNER JOIN `product_orders`
ON `product_orders`.`location_id` = `products`.`id`
WHERE `product_orders`.`location_id` = '2'
AND
status = 'sold'
DELETE FROM products WHERE id IN (SELECT location_id FROM products_orders WHERE location = 'miami' AND status = 'sold');
Try this one,
DELETE `products` FROM `products` INNER JOIN `products_orders`
ON `products_orders`.`location_id` = `products`.`id`
WHERE `products_orders`.`location` = 'miami'
AND
status = 'sold'
OR
DELETE prod FROM `products` AS prod INNER JOIN `products_orders`
ON `products_orders`.`location_id` = `products`.`id`
WHERE `products_orders`.`location` = 'miami'
AND
status = 'sold'
I am not sure how you have set foreign keys in your tables. But looking at it with the most primary assumptions, product table holds products data and location holds location data. In your common table product orders you are having one foreign key to products table by product id and one another relation to location table by location.
So to back my comment, I am posting the following query. It is your query with a change to a field that I ASSUME WAS A TYPO....in your query. :-) Again as foampile said, I might be doing it with consistency...
DELETE FROM `products`
INNER JOIN `products_orders`
ON `products_orders`.`product_id` = `products`.`id`
WHERE `products_orders`.`location` = 'miami'
AND `products_orders`.status = 'sold'
;