This question already has answers here:
How to select all records from one table that do not exist in another table?
(15 answers)
Closed 1 year ago.
I have two tables in my database: projects e invoices
Table invoices
CREATE TABLE `invoices` (
`id` int(11) NOT NULL,
`name` varchar(100) NOT NULL
);
INSERT INTO `invoices` (`id`, `name`) VALUES
(1, 'Invoice 1'),
(2, 'Invoice 2'),
(3, 'Invoice 3');
Table projects
CREATE TABLE `projects` (
`id` int(11) NOT NULL,
`invoice_id` int(11) NOT NULL,
`name` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Fazendo dump de dados para tabela `projects`
--
INSERT INTO `projects` (`id`, `invoice_id`, `name`) VALUES
(1, 1, 'Project name');
Expected result:
show rows
(2, 'Invoice 2'),
(3, 'Invoice 3')
If you want invoices where no project has that invoice, then one method uses not exists:
select i.*
from invoices i
where not exists (select 1
from projects p
where p.invoice_id = i.id
);
Related
I have four tables to map students and classes they attend, and to keep attendance info with start and end times.
Reproducible table schemas with records:
CREATE TABLE IF NOT EXISTS `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB;
INSERT INTO `student` (`id`, `name`) VALUES
(1, 'student 1'),
(2, 'student 2'),
(3, 'student 3'),
(4, 'student 4'),
(5, 'student 5');
CREATE TABLE IF NOT EXISTS `class` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
)ENGINE=InnoDB;
INSERT INTO `class` (`id`, `name`) VALUES
(1, 'class 1'),
(2, 'class 2');
CREATE TABLE IF NOT EXISTS `student_class` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`student_id` int(11) DEFAULT NULL,
`class_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`student_id`) REFERENCES `student` (`id`),
FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)
)ENGINE=InnoDB;
INSERT INTO `student_class` (`id`, `student_id`, `class_id`) VALUES
(1, 1, 1),
(2, 2, 1),
(3, 3, 1),
(4, 4, 2),
(5, 5, 2);
CREATE TABLE IF NOT EXISTS `attendance` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`student_class_id` int(11) DEFAULT NULL,
`start_time` time DEFAULT NULL,
`end_time` time DEFAULT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`student_class_id`) REFERENCES `student_class` (`id`)
)ENGINE=InnoDB;
INSERT INTO `attendance` (`id`, `student_class_id`, `start_time`, `end_time`) VALUES
(1, 1, '09:00:00', '10:00:00');
Problem:
I need to list down rows which only shows all attendance of a class to which at least one student attended,
(even if the rest of students have null for start_time, end_time).
Here is my current sql:
SELECT c.id classId, sc.id mapperId, a.start_time startTime, a.end_time endTime FROM class c
JOIN student_class sc ON sc.class_id = c.id
LEFT JOIN attendance a ON a.student_class_id = sc.id;
The result should look like this.
classId
mapperId
startTime
endTime
1
1
09:00:00
10:00:00
1
2
NULL
NULL
1
3
NULL
NULL
#user you can get the result set you are looking for my using another instance of your query modified slightly as a sub query, like this:
SELECT c.id classId,
sc.id mapperId,
a.start_time startTime,
a.end_time endTime
FROM class c
JOIN student_class sc ON sc.class_id = c.id
LEFT JOIN attendance a ON a.student_class_id = sc.id
WHERE `c`.`id` IN (
SELECT DISTINCT c.id classId
FROM class c
JOIN student_class sc ON sc.class_id = c.id
JOIN attendance a ON a.student_class_id = sc.id
)
Here is a mock up of the answer on sqlfiddle.com
Just add a condition for the class id
SELECT c.id classId, sc.id mapperId, a.start_time startTime,
a.end_time endTime FROM class c
JOIN student_class sc ON sc.class_id = c.id
LEFT JOIN attendance a ON a.student_class_id = sc.id
where c.id in (select distinct sc.class_id
from attendance a
join student_class sc
on a.student_class_id = sc.id);
Based on your question answer will be like this
SELECT cls.id, stdclass.id AS mapperId , att.start_time ,att.end_time FROM attendance att INNER JOIN student_class stdclass ON att.student_class_id = stdclass.id INNER JOIN class cls ON stdclass.class_id = cls.id INNER JOIN student std ON stdclass.student_id = std.id
We have orders and RMA's. RMA's can be created with order_products of an order. If in the RMA a new product is send, the product can also be added to a new RMA, and so on.
Now for example, I have this schematic structure of an order with RMA orders.
Order (1)
|-> RMA (2)
|-> RMA (3)
|-> RMA (4)
|-> RMA (5)
Now I want to traverse up from RMA (5), all the way up. So actually I want to get 5 records from the database containing all the RMA's and the original order (All from the order table). How can I do this, given the database structure shown below.
Here is a SQLFiddle.
CREATE TABLE `order` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(5) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
CREATE TABLE `order_product` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`order_id` int(11) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `order_rma_product` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`order_id` int(11) DEFAULT NULL,
`order_product_id` int(11) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
INSERT INTO `order` (`id`, `type`, `description`)
VALUES
(1, 'order', 'Original order'),
(2, 'rma', 'RMA of order 1'),
(3, 'rma', 'RMA of order 2'),
(4, 'rma', 'RMA of order 3'),
(5, 'rma', 'RMA of order 4');
INSERT INTO `order_product` (`id`, `order_id`, `description`)
VALUES
(1, 1, 'Product'),
(2, 2, 'Product'),
(3, 3, 'Product'),
(4, 4, 'Product');
INSERT INTO `order_rma_product` (`id`, `order_id`, `order_product_id`, `description`)
VALUES
(1, 2, 1, 'Return product'),
(2, 3, 2, 'Return product'),
(3, 4, 3, 'Return product'),
(4, 5, 4, 'Return product');
I have tried this, but this give's me one row, so i tried contact_ws to get them all in on column. But this only works for the given set of JOINS, so not unlimited going up.
SELECT CONCAT_WS(',', op.order_id, op1.order_id, op2.order_id)
FROM `order` o
JOIN order_rma_product orp ON o.id = orp.order_id
JOIN order_product op ON orp.order_product_id = op.id
JOIN order_rma_product orp1 ON op.order_id = orp1.order_id
JOIN order_product op1 ON orp1.order_product_id = op1.id
JOIN order_rma_product orp2 ON op1.order_id = orp2.order_id
JOIN order_product op2 ON orp2.order_product_id = op2.id
WHERE o.id = '5';
CREATE TABLE `Students` (
`id` int(11) NOT NULL,
`name` varchar(500) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `Students` (`id`, `name`) VALUES
(1, 'Student 1'),
(2, 'Student 2'),
(3, 'Student 3');
CREATE TABLE `lessons` (
`id` int(11) NOT NULL,
`name` varchar(500) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `lessons` (`id`, `name`) VALUES
(1, 'Lesson 1'),
(2, 'Lesson 2'),
(3, 'Lesson 3');
CREATE TABLE `completed` (
`student` int(11) NOT NULL,
`lesson` varchar(500) NOT NULL,
`completed` int(11) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `completed` (`student`, `lesson`, `completed`) VALUES
(1, 2, 1),
(3, 3, 1),
(2, 1, 1);
we are adding students who completed lessons to "completed" table. we need to get 5 student with lesson which id not exists in "completed" table.
example output is;
1, 1
1, 3
2, 2
2, 3
3, 1
3, 2
thank you
You can use NOT EXISTS
SELECT s.Id, s.Name
FROM Students s
WHERE NOT EXISTS (
SELECT 1
FROM Completed
WHERE s.Id = student
)
Following should show all of the students that don't have a completed lesson, which is what I think you're asking for:
SELECT Students.id, Students.name FROM Students LEFT JOIN completed
ON Students.id = completed.student WHERE completed.student IS NULL;
how to get vistors_sum and reviews_count in 3 table ?
see the bellow codes, how to get my result in one sql?
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `a`
-- ----------------------------
DROP TABLE IF EXISTS `a`;
CREATE TABLE `a` (
`products_id` int(11) NOT NULL,
`products_name` varchar(255) default NULL,
PRIMARY KEY (`products_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of a
-- ----------------------------
INSERT INTO `a` VALUES ('1', 'jimmy');
INSERT INTO `a` VALUES ('2', 'tina');
INSERT INTO `a` VALUES ('3', 'emma');
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `b`
-- ----------------------------
DROP TABLE IF EXISTS `b`;
CREATE TABLE `b` (
`id` int(11) NOT NULL auto_increment,
`products_id` int(11) NOT NULL,
`vistors` int(11) NOT NULL,
`date` date default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of b
-- ----------------------------
INSERT INTO `b` VALUES ('1', '1', '1', '2013-11-13');
INSERT INTO `b` VALUES ('2', '1', '2', '2013-11-04');
INSERT INTO `b` VALUES ('3', '2', '1', '2013-11-13');
INSERT INTO `b` VALUES ('4', '2', '3', '2013-11-13');
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `c`
-- ----------------------------
DROP TABLE IF EXISTS `c`;
CREATE TABLE `c` (
`id` int(11) NOT NULL auto_increment,
`products_id` int(11) NOT NULL,
`review_content` varchar(255) default NULL,
`date` date default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of c
-- ----------------------------
INSERT INTO `c` VALUES ('1', '1', 'hello', '2013-11-13');
INSERT INTO `c` VALUES ('2', '1', 'world', '2013-11-13');
INSERT INTO `c` VALUES ('3', '2', 'good', '2013-11-12');
INSERT INTO `c` VALUES ('4', '3', 'boy', '2013-11-13');
this code bellow can do but the date condition is in sub children temp table. this make the sql not flexible (if I want to query any time not 2013-11-13)
select
a.products_id,
a.products_name,
b.vistors_sum,
c.reviews_count
from
a
left join
(
select
b.products_id,
b.date,
sum(b.vistors) as vistors_sum
from b
where b.date = '2013-11-13'
group by b.products_id
) as b on a.products_id = b.products_id
left join
(
select
c.products_id,
count(c.products_id) as reviews_count
from c
where c.date = '2013-11-13'
group by c.products_id
) as c on a.products_id = c.products_id
SQLFiddle demo
select a.products_id,
products_name,
COALESCE(b.sum_visitors,0) as sum_visitors,
COALESCE(c.count_comments,0) as count_comments
from a
left join
( SELECT products_id,sum(vistors) as sum_visitors
FROM b
WHERE date='2013-11-13'
GROUP BY products_id
) as b
on (a.products_id=b.products_id)
left join
(
SELECT products_id,count(*) as count_comments
FROM c
WHERE date='2013-11-13'
GROUP BY products_id
) as c
on (a.products_id=c.products_id)
how can i get the result as bellow in mysql?
I want to get all products group by id and show what categories it belongs to.
how can I get it in one sql ?
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `a`
-- ----------------------------
DROP TABLE IF EXISTS `a`;
CREATE TABLE `a` (
`products_id` int(11) NOT NULL,
`products_name` varchar(255) default NULL,
PRIMARY KEY (`products_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of a
-- ----------------------------
INSERT INTO `a` VALUES ('1', 'hello');
INSERT INTO `a` VALUES ('2', 'world');
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `b`
-- ----------------------------
DROP TABLE IF EXISTS `b`;
CREATE TABLE `b` (
`products_id` int(11) NOT NULL,
`categories_id` int(11) NOT NULL,
PRIMARY KEY (`products_id`,`categories_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of b
-- ----------------------------
INSERT INTO `b` VALUES ('1', '1');
INSERT INTO `b` VALUES ('1', '2');
INSERT INTO `b` VALUES ('2', '1');
INSERT INTO `b` VALUES ('2', '3');
This is what you want?
SELECT a.products_id, a.products_name,
GROUP_CONCAT(CONVERT(b.categories_id,CHAR(8))) as products_to_categories
FROM a,b
WHERE a.products_id = b.products_id
GROUP BY a.products_id, a.products_name
fiddle at http://www.sqlfiddle.com/#!2/39edfc/3/0
Resulting image in fiddle
there are alternative way by using inner join, cheer =)
SELECT a.products_id, a.products_name,group_concat(b.categories_id)
FROM a
INNER JOIN b ON a.products_id = b.products_id
group by a.products_id, a.products_name