subquery in IN clause? - mysql

I have two tables named as
product_Category
CREATE TABLE `product_category` (
`pid` int(11) NOT NULL,
`cid` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `product_category`
--
/*!40000 ALTER TABLE `product_category` DISABLE KEYS */;
INSERT INTO `product_category` (`pid`,`cid`) VALUES
(1,1),
(2,3),
(3,2),
(4,2),
(5,3),
(1,2),
(2,4),
(3,1);
and category table
CREATE TABLE `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cat_name` varchar(50) NOT NULL,
`mapped_cat_id` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `category`
--
/*!40000 ALTER TABLE `category` DISABLE KEYS */;
INSERT INTO `category` (`id`,`cat_name`,`mapped_cat_id`) VALUES
(1,'c1','1,2,4'),
(2,'c2','2,3'),
(3,'c3','3,4'),
(4,'c4','4,1,3');
/*!40000 ALTER TABLE `category` ENABLE KEYS */;
When I run this query
select distinct pid from
product_category where cid in (1,2,4)
I got result of pid (1,3,4,2)
but when I run query
select distinct pid from
product_category where cid in (select mapped_cat_id from category where id=1)
I got result of pid (1,3)
How to use subquery with 'IN' clause ?
I know my way of asking question is wrong because I dont know how to create table here thats why I wrote query instead of table.

i think coma separated values are not good.
Delete contents of your category table and use following query to insert
INSERT INTO `category` (`id`, `cat_name`, `mapped_cat_id`) VALUES
(1, 'c1', '1'),
(2, 'c2', '2'),
(3, 'c3', '3'),
(4, 'c4', '4'),
(5, 'c1', '2'),
(6, 'c1', '4'),
(7, 'c2', '3'),
(8, 'c3', '4'),
(9, 'c4', '1'),
(10, 'c4', '3');
Then use following query to get your result
select distinct pid from
product_category where cid in
(select mapped_cat_id from category where cat_name='c1')

You might be looking for FIND_IN_SET() function
select distinct pid from
product_category where FIND_IN_SET(cid,
(select mapped_cat_id from category where id=1));
SAMPLE FIDDLE
Since mapped_cat_id is saved as comma - seperated values(varchar), it is taking only first integer for the condition checking. Here it is 1

Related

How to implement IF condition in two relational tables?

I have two relational tables, and I would like to filter data using IF condition. The problem is that using LEFT JOIN I got records that cannot be grouped.
The tables that I have are:
calendar
bookers
The first table consists of lessons that can be booked by more people, and the second table contains data who booked each lesson. The IF condition that I would like to implement is: return '2' if lesson is booked by specific user, return '1' if lesson is booked, but by another user, and return '0' if lesson is not booked.
What I would like to get according to above tables is given in the figure below.
Expected result
But, when I use LEFT JOIN to link those tables, I got record for every user that booked specific lesson.
SELECT calendar.id, calendarId, lessonType, description,
CASE
WHEN bookedBy then IF(bookedBy = 8, '2', '1')
ELSE '0'
END AS bb,
(select count(bookedBy) from bookers where calendar.id = bookers.lessonId) as nOfBookers
FROM calendar
LEFT JOIN bookers ON calendar.id = bookers.lessonId
WHERE `calendarId`= 180
Without the LEFT JOIN (fiddle), counts are shown properly, but I cannot include IF condition, because the table bookers is not defined.
I would appreciate any help. Thank you very much in advance.
Here is the Fiddle.
CREATE TABLE `calendar` (
`id` int(11) NOT NULL,
`calendarId` varchar(50) NOT NULL,
`lessonType` varchar(255) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `calendar`
(`id`, `calendarId`, `lessonType`, `description`)
VALUES
(1, '180', 'A', ''),
(2, '180', 'A', ''),
(3, '180', 'A', ''),
(4, '180', 'B', ''),
(5, '180', 'B', ''),
(6, '180', 'B', ''),
(7, '180', 'B', ''),
(8, '180', 'B', ''),
(9, '180', 'B', '');
CREATE TABLE `bookers` (
`id` int(11) NOT NULL,
`lessonId` int(11) DEFAULT NULL,
`bookedBy` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Dumping data for table `bookers`
--
INSERT INTO `bookers` (`id`, `lessonId`, `bookedBy`) VALUES
(4, 1, 8),
(5, 2, 8),
(6, 2, 28),
(7, 2, 17),
(8, 3, 11);
--
-- Indexes for dumped tables
--
ALTER TABLE `calendar`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `id` (`id`);
--
-- Indexes for table `bookers`
--
ALTER TABLE `bookers`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `bookers`
--
ALTER TABLE `bookers`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9;
COMMIT;
select version();
Try this:
SELECT id, calendarid, lessontype, description,
CASE WHEN FIND_IN_SET(8,vbb)>0 THEN 2
WHEN vbb IS NOT NULL THEN 1
ELSE 0 END AS bb,
nOfBookers
FROM
(SELECT c.id, calendarId, lessonType, GROUP_CONCAT(bookedby) AS vbb, description,
(SELECT COUNT(bookedby) FROM bookers WHERE c.id = bookers.lessonId) AS nOfBookers
FROM calendar c
LEFT JOIN bookers b ON c.id = b.lessonId
WHERE `calendarId`= 180
GROUP BY c.id, calendarId, lessonType, description) A;
In addition to your original LEFT JOIN attempt, I've added GROUP_CONCAT(bookedby) AS vbb which will return a comma separated bookedby value; which is 17,28,8. After that, I make the query as a sub-query and do CASE expression with FIND_IN_SET function on vbb to look for specific bookedby.
Here's an update fiddle: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=0933e9fc3cb7445311c34c6705d11637

How to find count in many to many relationship in MySql, Cakephp 3.6

I need to calculate the count(vendors.id) for each category.
ie: how many vendors are there for each category(not sub-category)
I am using cakephp 3.6 framework and MySQL as database
I tried with all possible way that i knew but not found any solution. Can anybody help me, is very important for my project
[UPDATE]
sql query i have used:
SELECT cat.id,cat.name ,COUNT(`vendor_id`) AS vendor_count FROM `vendor_services` JOIN `categories` ON(`vendor_services`.`category_id` = `categories`.`id`) JOIN `categories` AS cat ON(categories.category_id = cat.id) WHERE 1 GROUP BY cat.id
[UPDATE]Bellow is the sql to create corresponding tables
-- phpMyAdmin SQL Dump
-- version 4.7.0
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: Dec 04, 2018 at 10:50 AM
-- Server version: 10.1.24-MariaDB
-- PHP Version: 7.1.6
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
--
-- Database: `demo123`
--
-- --------------------------------------------------------
--
-- Table structure for table `categories`
--
CREATE TABLE `categories` (
`id` int(11) NOT NULL,
`category_id` tinyint(4) NOT NULL,
`name` varchar(60) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `categories`
--
INSERT INTO `categories` (`id`, `category_id`, `name`) VALUES
(1, 0, 'Books'),
(2, 0, 'Electronics'),
(3, 0, 'Garden'),
(4, 1, 'Novel'),
(5, 1, 'Science'),
(6, 1, 'Story'),
(7, 2, 'Mobile'),
(8, 2, 'Tablet'),
(9, 2, 'Headphone'),
(10, 3, 'Pumps'),
(11, 3, 'Pipes');
-- --------------------------------------------------------
--
-- Table structure for table `vendors`
--
CREATE TABLE `vendors` (
`id` int(11) NOT NULL,
`name` varchar(60) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `vendors`
--
INSERT INTO `vendors` (`id`, `name`) VALUES
(1, 'VR Enterprizes'),
(2, 'RR Vendors'),
(3, 'JK Suppliers');
-- --------------------------------------------------------
--
-- Table structure for table `vendor_services`
--
CREATE TABLE `vendor_services` (
`id` int(11) NOT NULL,
`vendor_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `vendor_services`
--
INSERT INTO `vendor_services` (`id`, `vendor_id`, `category_id`) VALUES
(1, 1, 4),
(2, 1, 5),
(3, 1, 6),
(4, 1, 11),
(5, 2, 7),
(6, 2, 8),
(7, 2, 9),
(8, 3, 10),
(9, 3, 11);
--
-- Indexes for dumped tables
--
--
-- Indexes for table `categories`
--
ALTER TABLE `categories`
ADD PRIMARY KEY (`id`),
ADD KEY `category_id` (`category_id`);
--
-- Indexes for table `vendors`
--
ALTER TABLE `vendors`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `vendor_services`
--
ALTER TABLE `vendor_services`
ADD PRIMARY KEY (`id`),
ADD KEY `vendor_id` (`vendor_id`),
ADD KEY `category_id` (`category_id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `categories`
--
ALTER TABLE `categories`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12;
--
-- AUTO_INCREMENT for table `vendors`
--
ALTER TABLE `vendors`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT for table `vendor_services`
--
ALTER TABLE `vendor_services`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10;COMMIT;
CategoriesTable
$this->hasMany(‘Subcategories’, [ 'className'=> ‘Categories’,
'foreignKey' => 'category_id',
'conditions' => ['category_id!= 0']
]);
$this->belongsTo('MainCategories', [
'className'=> ‘Categories’,
'foreignKey' => 'category_id',
]);
Below is the query in oracle, please have a look, and modify it as per mysql,
added below insertion,
INSERT INTO VENDOR_SERVICES (ID, VENDOR_ID, CATEGORY_ID)
VALUES(11, 3, 3);
SELECT FRM.CATEGORY_ID, FRM.VENDOR_ID, FRM.VENDER_NAME,COUNT(VENDOR_ID) counts FROM (
SELECT distinct CT.CATEGORY_ID, VS.VENDOR_ID, VS.CATEGORY_ID VS_CATEGORY_ID,vn.ID, vn.NAME VENDER_NAME FROM CATEGORIES CT
INNER JOIN VENDOR_SERVICES VS ON VS.CATEGORY_ID=CT.CATEGORY_ID
INNER JOIN VENDORS VN ON VS.VENDOR_ID=VN.ID) frm
group by CATEGORY_ID, VENDOR_ID, VENDER_NAME

mysql how to sort based on relationship field

i stumbled the following problem that i cannot solve
i have the following table in the database
CREATE TABLE `departments` (
`Company` int(11) NOT NULL,
`Department` varchar(32) NOT NULL,
`DepartmentName` varchar(40) NOT NULL,
`parentDepartment` varchar(32) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `departments` (`Company`, `Department`, `DepartmentName`, `parentDepartment`) VALUES
(1, '1', 'Company1 Ltd', '1'),
(1, '101', 'Information Technology', '1'),
(1, '10101', 'Hardware', '101'),
(1, '10102', 'Software', '101'),
(1, '102', 'Sales Department', '1'),
(1, '10201', 'Travelling', '101');
COMMIT;
basically its a list of departments in the company. Each department can be "nested" under another using the "parentDepartment" field.
Department field is the code of the department. But the numbering is irrelevant to the "structure".
what i want to achieve can be viewed in the picture bellow.
The question is how to sort this table out and keep the relationships visible?
Thank you
Try this:
SELECT *
FROM departments
ORDER BY department;

Converting SQL file To CSV

I have dumped a sql table for cities, regions & countries.
I have the .sql files in my local machine. I need to convert them to CSV format.
So I have a 2 part question.
1): What is the best way to do this? Is any tools I can use? (I have a Mac)
2):
I found this site. So I tried with this code:
CREATE TABLE IF NOT EXISTS `countries` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`code` varchar(10) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=231 DEFAULT CHARSET=latin1;
-- Dumping data for table dddblog.countries: ~218 rows (approximately)
/*!40000 ALTER TABLE `countries` DISABLE KEYS */;
INSERT INTO `countries` (`id`, `name`, `code`) VALUES
(1, 'Andorra', 'ad'),
(2, 'United Arab Emirates', 'ae'),
(3, 'Afghanistan', 'af'),
(4, 'Antigua and Barbuda', 'ag'),
(5, 'Anguilla', 'ai'),
(6, 'Albania', 'al'),
(7, 'Armenia', 'am'),
(8, 'Netherlands Antilles', 'an'),
(9, 'Angola', 'ao'),
// Other countries
/*!40000 ALTER TABLE `countries` ENABLE KEYS */;
And when I click on Convert, I get error: Missing SELECT STATEMENT.
Im not familiar with SQL and any help is appreciated!
The message Missing SELECT STATEMENT says it all: You have to add a SELECT statement.
Try it with this code - worked for me:
CREATE TABLE IF NOT EXISTS `countries` (
`id` smallint(5) NOT NULL ,
`name` varchar(255) NOT NULL,
`code` varchar(10) NOT NULL
);
INSERT INTO `countries` (`id`, `name`, `code`) VALUES
(1, 'Andorra', 'ad'),
(2, 'United Arab Emirates', 'ae'),
(3, 'Afghanistan', 'af'),
(4, 'Antigua and Barbuda', 'ag'),
(5, 'Anguilla', 'ai'),
(6, 'Albania', 'al'),
(7, 'Armenia', 'am'),
(8, 'Netherlands Antilles', 'an'),
(9, 'Angola', 'ao')
;
SELECT `id`, `name`, `code` FROM `countries`

Getting List of records with No related records MySQL

I wish to know which team in "TX" have not played a game. (In other words Im looking for a selection of records where there is no related record in the many table.)
Here is the SQL:
(Or if You prefer the sql fiddle is here:http://sqlfiddle.com/#!2/14106 )
CREATE TABLE `Team` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`Name` VARCHAR(45) NULL ,
`State` VARCHAR(45) NULL ,
PRIMARY KEY (`ID`) );
CREATE TABLE `Games` (
`ID` INT NOT NULL AUTO_INCREMENT,
`Team_ID` INT NULL ,
`Game_Day` DATE NULL ,
PRIMARY KEY (`ID`) );
INSERT INTO `Team` (`Name`, `State`) VALUES ('Rams', 'TX');
INSERT INTO `Team` (`Name`, `State`) VALUES ('Rockets', 'OK');
INSERT INTO `Team` (`Name`, `State`) VALUES ('Bombers', 'TX');
INSERT INTO `Team` (`Name`, `State`) VALUES ('Yellow Jackets', 'NV');
INSERT INTO `Team` (`Name`, `State`) VALUES ('Wildcats', 'CT');
INSERT INTO `Team` (`Name`, `State`) VALUES ('Miners', 'CO');
INSERT INTO `Team` (`Name`, `State`) VALUES ('Bolts', 'TX');
INSERT INTO `Games` (`Team_ID`, `Game_Day`) VALUES ('2', '2013-03-16');
INSERT INTO `Games` (`Team_ID`, `Game_Day`) VALUES ('2', '2013-01-01');
INSERT INTO `Games` (`Team_ID`, `Game_Day`) VALUES ('3', '2013-04-16');
INSERT INTO `Games` (`Team_ID`, `Game_Day`) VALUES ('5', '2013-02-02');
INSERT INTO `Games` (`Team_ID`, `Game_Day`) VALUES ('4', '2013-02-12');
INSERT INTO `Games` (`Team_ID`, `Game_Day`) VALUES ('6', '2013-01-09');
INSERT INTO `Games` (`Team_ID`, `Game_Day`) VALUES ('6', '2013-01-01');
INSERT INTO `Games` (`Team_ID`, `Game_Day`) VALUES ('3', '2013-05-01');
I should get the result:
ID Name
1 Rams
7 Bolts
SELECT `ID`, `Name` FROM `TEAM`
WHERE `ID` NOT IN (SELECT DISTINCT(`Team_ID`) from `Games`)
AND `State` = 'TX';
SqlFiddle here.
Use an outer join, selecting only those rows that don't match
SELECT t.*
FROM TEAM t
LEFT JOIN GAMES g ON g.team_id = t.id
WHERE t.state = 'TX'
AND g.team_id is null -- return only rows that *don't* join
This this running in SQL Fiddle
Note that using a join will out-perform a sub-query approach, especially when data sets become large.
You can also left-join to the Games table and filter for where there isn't a corresponding Games row. This is usually faster than NOT IN when the tables have a lot of rows:
SELECT Team.ID, Team.Name
FROM Team
LEFT JOIN Games ON Team.ID = Games.Team_ID
WHERE Team.State = 'TX' AND Games.ID IS NULL;
If there isn't a Games row to go with the Teams row, the Games.ID column will be null in the result, so if you filter on Games.ID IS NULL you'll get all the rows where a team has no games.
There's a SQL Fiddle here.
Hope this would help.
select t.ID,t.NAME
FROM Team t
WHERE t.state = 'TX'
AND t.id NOT IN (SELECT g.TEAM_ID FROM Games g)