mysql finding not exist records in mutiple tables - mysql

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;

Related

Show difference between two tables in mysql using join [duplicate]

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
);

Calculating sum of a values after join

I have these tables:
CREATE TABLE `items` (
`itemId` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`itemCategoryId` mediumint(8) unsigned DEFAULT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`itemId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `orders` (
`orderId` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`customerId` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`orderId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `orders_items` (
`orderItemId` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`orderId` mediumint(8) unsigned NOT NULL,
`itemId` mediumint(8) unsigned NOT NULL,
`price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00',
PRIMARY KEY (`orderItemId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `order_items_quantity` (
`orderItemId` mediumint(8) unsigned NOT NULL,
`size` tinyint(3) unsigned DEFAULT NULL,
`quantity` smallint(5) unsigned NOT NULL,
UNIQUE KEY `unique` (`orderItemId`,`size`,`quantity`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `items` (`itemId`, `itemCategoryId`, `name`)
VALUES
(1, 1, 'Jeans Model A (Category Jeans)'),
(2, 1, 'Jeans Model B (Category Jeans)'),
(3, 2, 'T-Shirt Model A (Category T-Shirt)');
INSERT INTO `orders` (`orderId`, `customerId`)
VALUES
(1, 1),
(2, 2),
(3, 1);
INSERT INTO `orders_items` (`orderItemId`, `orderId`, `itemId`)
VALUES
(1, 1, 1),
(2, 1, 2),
(3, 2, 1),
(4, 2, 2),
(5, 3, 1),
(6, 3, 3);
INSERT INTO `order_items_quantity` (`orderItemId`, `size`, `quantity`)
VALUES
(1, 1, 2),
(1, 2, 3),
(2, 1, 3),
(2, 2, 5),
(3, 1, 1),
(3, 2, 2),
(4, 1, 1),
(4, 2, 1),
(5, 1, 4),
(6, 1, 3);
I can't merge 'order_items' with 'order_items_quantity' because I have other fields in the first table about the items regardless the size (es. their prices in that moment) that would be wasted disk space if I repeat them in only one table.
I need a query to get the sum of all the ordered quantities of any item of a certain category by each customer regerdless of the size. Something like:
customerId itemCategoryId total_quantity_ordered
1 1 17
2. 1 5
2. 2. 3
I wrote this query:
SELECT total_quantities.total_quantity_ordered, orders.customerId, items.itemCategoryId FROM orders
JOIN (
SELECT orders_items.orderId, SUM(order_items_quantity.quantity) AS total_quantity_ordered
FROM orders_items
JOIN order_items_quantity ON order_items_quantity.orderItemId=orders_items.orderItemId
GROUP BY orders_items.orderId
) AS total_quantities ON total_quantities.orderId=orders.orderId
JOIN orders_items ON orders_items.orderId=orders.orderId
JOIN items ON items.itemId=orders_items.itemId
GROUP BY orders.customerId, items.itemCategoryId
but it selects only the first order of every customer containing that categoryId. Any help is appreciated.
SQL Fiddle: https://www.db-fiddle.com/f/bnxomXfobBN25nTJvASVdL/0
You don't need the subquery:
SELECT o.customerId, i.itemCategoryId SUM(q.quantity) AS total_quantity_ordered
FROM orders o
INNER JOIN orders_items oi ON oi.orderId=o.orderId
JOIN order_items_quantity q ON oi.orderItemId=q.orderItemId
JOIN items i ON i.itemId=oi.itemId
GROUP BY o.customerId, i.itemCategoryId

SQL sorted by a diferent fields

I have the next tables and rows. And I need to write a SELECT that returns all categories sorted by:
(A) the number of items they have
and (B) the category name.
This query should fetch the following columns: the category name, the number of items (AS N_ITEMS) and the average price of the titles in that category (AS AVERAGE_PRICE)
CREATE TABLE `category` (
`CATEGORY_ID` int(11) NOT NULL,
`CATEGORY_NAME` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `category` (`CATEGORY_ID`, `CATEGORY_NAME`) VALUES
(1, 'Sports'),
(2, 'Actualités'),
(3, 'Animaux'),
(4, 'Economie'),
(5, 'Cuisine');
CREATE TABLE `item` (
`ITEM_ID` int(11) NOT NULL,
`CATEGORY_ID` int(11) NOT NULL,
`ITEM_NAME` varchar(50) NOT NULL,
`ITEM_PRICE` decimal(8,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `item` (`ITEM_ID`, `CATEGORY_ID`, `ITEM_NAME`, `ITEM_PRICE`) VALUES
(1, 1, 'Equip', '6.00'),
(2, 2, 'Le Monde', '3.00'),
(3, 2, 'Le Parisien', '2.50'),
(4, 2, 'France soir', '3.00'),
(5, 3, '30 Million damis', '6.20'),
(6, 3, 'Cheval pratique', '4.50'),
(7, 4, 'Capital', '2.50');
ALTER TABLE `category`
ADD PRIMARY KEY (`CATEGORY_ID`);
ALTER TABLE `item`
ADD PRIMARY KEY (`ITEM_ID`);
ALTER TABLE `category`
MODIFY `CATEGORY_ID` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `item`
MODIFY `ITEM_ID` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
You can try below -
select CATEGORY_NAME, count(ITEM_ID) as noofItem,avg(item_price) as avgprice
from category inner join item on category.category_id=item.category_id
group by CATEGORY_NAME
order by noofItem,CATEGORY_NAME

MySQL get all parents

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';

showing counter in mysql query

I have mysql query given below. I which counter has been used. if i enter category Id 1 for 3 times then counter is coming 3 which is correct but with this i want if i do not enter then different coloumn should come with NO.
output should be
KU Electrical
Yes 6 2
No 1 2
In this KU and Electrical are my sale channel name. Yes means counter of enteries of KU and No means which have not entered. Please help out in this. i am struggling
select
SalesChannel.name,
Transaction.category_id,
count(Transaction.category_id) as "count"
from outlets Outlet
inner join transactions Transaction on Outlet.id = Transaction.outlet_id
inner join sale_channels SalesChannel on SalesChannel.id = Outlet.sale_channel_id
group by Transaction.category_id;
below are three tables which I used
1) transactions
CREATE TABLE IF NOT EXISTS `transactions` (
`id` int(11) NOT NULL,
`zone_id` int(11) NOT NULL,
`state_id` int(11) NOT NULL,
`city_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
`sub_category_id` int(11) NOT NULL,
`brand_id` int(11) NOT NULL,
`model_id` int(11) NOT NULL,
`outlet_id` int(11) NOT NULL,
`no_of_units` int(11) NOT NULL,
`mop` decimal(10,2) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `transactions`
--
INSERT INTO `transactions` (`id`, `zone_id`, `state_id`, `city_id`, `category_id`, `sub_category_id`, `brand_id`, `model_id`, `outlet_id`, `no_of_units`, `mop`) VALUES
(1, 2, 2, 2, 2, 1, 1, 1, 1, 3, '6.00'),
(2, 2, 2, 2, 2, 1, 1, 1, 1, 3, '6.00'),
(3, 1, 1, 1, 1, 1, 1, 1, 1, 4, '2.00'),
(4, 2, 2, 2, 1, 1, 1, 1, 2, 4, '2.00');
2) outlets
CREATE TABLE IF NOT EXISTS `outlets` (
`id` int(11) NOT NULL,
`outlet_code` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`zone_id` int(11) NOT NULL,
`state_id` int(11) NOT NULL,
`city_id` int(11) NOT NULL,
`sale_channel_id` int(11) NOT NULL,
`is_active` tinyint(1) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `outlets`
--
INSERT INTO `outlets` (`id`, `outlet_code`, `name`, `zone_id`, `state_id`, `city_id`, `sale_channel_id`, `is_active`, `created`, `modified`) VALUES
(1, '1508', 'Ashok electricals', 2, 2, 2, 1, 1, '2016-10-03 00:00:00', '2016-10-03 00:00:00'),
(2, '1233', 'vinayak electricals', 1, 1, 1, 2, 1, '2016-10-04 00:00:00', '2016-10-04 00:00:00');
3) sale_chennals
CREATE TABLE IF NOT EXISTS `sale_channels` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`is_active` tinyint(1) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `sale_channels`
--
INSERT INTO `sale_channels` (`id`, `name`, `is_active`, `created`, `modified`) VALUES
(1, 'KU', 1, '2016-10-03 00:00:00', '2016-10-03 00:00:00'),
(2, 'Electricals', 1, '2016-10-04 00:00:00', '2016-10-04 00:00:00');
SQL fiddle: http://sqlfiddle.com/#!9/3f497/1
You are grouping by category. That means you get one result row per category. In each of these rows you show the count and a sale channel name. This sale channel name is just one of the names found in the records for the category arbitrarily chosen.
I suppose you want to count per category and sale channel. Hence your group by clause should be group by SalesChannel.name, Transaction.category_id:
select
SalesChannel.name,
Transaction.category_id,
count(Transaction.category_id) as "count"
from outlets Outlet
inner join transactions Transaction on Outlet.id = Transaction.outlet_id
inner join sale_channels SalesChannel on SalesChannel.id = Outlet.sale_channel_id
group by SalesChannel.name, Transaction.category_id;
SQL fiddle: http://sqlfiddle.com/#!9/3f497/2
This result, however, doesn't show an entry for Electricals / category 2, because there is no transaction for this combination in the table. If you want to show a zero count for this, you'd have to create the complete result set (i.e. all combinations of channel and category, whether they have a transaction or not) first. Then you'd outer join the transactions:
select
sc.name,
c.id as category_id,
count(t.id) as "count"
from sale_channels sc
cross join categories c
left join outlets o on o.sale_channel_id = sc.id
left join transactions t on t.outlet_id = o.id and t.category_id = c.id
group by sc.name, c.id;
SQL fiddle: http://sqlfiddle.com/#!9/60e998/5