JOIN four tables to create an restaurant menustructure - mysql

I have four tables I would like to join to the tables in the picture below
This is what i have come up with for now:
SELECT
category.category_id,
category.name,
menuitems.name AS menu_name,
restaurant.restaurant_id
FROM
category
JOIN
restaurant_has_category
ON
category.category_id = restaurant_has_category.category_id
AND
restaurant_has_category.category_id = category.category_id
JOIN
restaurant
JOIN
menuitems
The result is this:
As you can see I'm getting duplicates and the query thinks that the category name and menuItem name aren't distinct. I would love to show which categories a restaurant have AND then I would love to show all the different menuItems in each category
In the writing of this I realise that I need a separate query for all my menuItems ?
Can you see what im going for ? and my problem?
AS REQUESTED HERE IS THE CODE instead of pictures
CREATE TABLE IF NOT EXISTS `category` (
`category_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`description` MEDIUMTEXT,
`image` VARCHAR(255),
PRIMARY KEY (`category_id`)
);
CREATE TABLE IF NOT EXISTS `restaurant` (
`restaurant_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(150) NOT NULL,
`description` MEDIUMTEXT NOT NULL,
`image` VARCHAR(255),
`URL` VARCHAR(255),
`email` VARCHAR(100),
`openingHours` VARCHAR(255),
`CVR` INT(45),
`telephone` INT(45),
`place_id` INT(10) NOT NULL,
PRIMARY KEY (`restaurant_id`),
FOREIGN KEY (`place_id`) REFERENCES place(`place_id`)
);
CREATE TABLE IF NOT EXISTS `restaurant_has_category` (
`restaurant_id` INT(10) UNSIGNED NOT NULL,
`category_id` INT(10) NOT NULL,
PRIMARY KEY (`restaurant_id`, `category_id`),
FOREIGN KEY (`restaurant_id`) REFERENCES restaurant(`restaurant_id`),
FOREIGN KEY (`category_id`) REFERENCES category(`category_id`)
);
CREATE TABLE IF NOT EXISTS `menuItems` (
`menuItems_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`toppings` VARCHAR(250),
`price` INT(10) NOT NULL,
`size` VARCHAR(50) NOT NULL,
`category_id` INT(10) NOT NULL,
PRIMARY KEY (`menuItems_id`),
FOREIGN KEY (`category_id`) REFERENCES category(`category_id`)
);
Here are som sample data to play around with;
INSERT INTO `menuitems` (`menuItems_id`, `name`, `toppings`, `price`,
`size`, `category_id`) VALUES
(1, 'Margherita', 'Tomatsovs, Ost', 55, '1pers', 1),
(4, 'Cheese Burger', 'Ost, salat, oksebøf', 89, '', 3),
(7, 'Durum rulle', 'Kebab, salat, tomat, agurk, skinke', 67, '', 2);
INSERT INTO `category` (`category_id`, `name`, `description`, `image`)
VALUES
(1, 'Pizza', 'beskrivelse', 'foto'),
(2, 'Ruller', 'beskrivelse', 'foto'),
(3, 'Burger', 'beskivelse', 'foto');
INSERT INTO `restaurant_has_category` (`restaurant_id`, `category_id`)
VALUES
(2, 1),
(2, 2),
(2, 3);
INSERT INTO `restaurant` (`restaurant_id`, `name`, `description`, `image`,
`URL`, `email`, `openingHours`, `CVR`, `telephone`, `place_id`) VALUES
(2, 'Alforno Pizza', 'Lorem ipsum dolor, description text here',
'https://migogkbh.dk/wp-content/uploads/2018/10/Kiin-Kiin-Bao-Bao-Foto-
Rasmus-Schou.jpg', 'hjemmeside', 'email#email.com', 'mo - th: 09:00', 0,
11223344, 1);
THIS IS THE FORMAT I'M SEEKING
category_id | category.name | menu_name | restaurant_id
1 Pizza Margherita 2
1 Pizza Kebab pizza 2
2 Burger Kebab burger 2
2 Burger Cheese burger 2
3 Durum kebab 2

You are getting duplication and misinformation because restaurant and menuitems are cross-joined to each other and the other tables. Fix your FROM clause and you will get the data you expect.
You can find basic SQL tutorials all over the web. My favorite beginner SQL training is at W3CSchools.com. But don't stop there. You should also try to understand set relationships and how those are defined in terms of SQL code. I find presentations that use Venn diagrams can be helpful.

Related

Joining data from 3 separate MySQL tables

I have 3 MySQL tables: person, review & team.
I have been able to join 2 (person & review) together, however I'd like to include data from the 3rd in my result.
Can someone explain how this is done? :-)
CREATE TABLE `person` (
`id` int NOT NULL AUTO_INCREMENT,
`reference` varchar(100) NOT NULL,
`email` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
INSERT INTO `person` (`id`, `reference`, `email`) VALUES
(1, 'PK001', 'paulk#gmail.com');
CREATE TABLE `review` (
`id` int NOT NULL AUTO_INCREMENT,
`review_type` varchar(255) NOT NULL,
`review_body` varchar(255) NOT NULL,
`person_id` int NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
INSERT INTO `review` (`id`, `review_type`, `review_body`, `person_id`) VALUES
(1, 'Personality', 'He has a great personality!', 1),
(2, 'Skills', 'He has multiple skills!', 1);
CREATE TABLE `team` (
`id` int(11) NOT NULL,
`person_id` int(11) NOT NULL,
`team_name` varchar(255) NOT NULL,
`value` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
INSERT INTO `team` (`id`, `person_id`, `team_name`, `value`) VALUES
(1, 1, 'Man Utd', 500),
(2, 1, 'Real Madrid', 1500),
(3, 1, 'Ajax', 1000);
Using the following SQL:
SELECT p.id, group_concat(r.review_body)
FROM person p
inner join review r on r.person_id = p.id
group by p.id
gives me the output:
He has a great personality!,He has multiple skills!
However I'd ultimately like my output to be:
He has multiple skills!,He has a great personality,Man Utd-500|Real Madrid-1500|Ajax-1000
Is this possible to do with MySQL ? Any guidance would be greatly appreciated.
I realise I could optimise things a lot better - but I just want to see if I can connect all 3 tables together and go from there.
To get your required concatenated output you need to modify your join query.
For that your new query looks like this:
SELECT p.id,
GROUP_CONCAT(r.review_body) AS reviews,
(SELECT GROUP_CONCAT(CONCAT(team_name, '-', value) SEPARATOR '|')
FROM team
WHERE team.person_id = p.id) AS teams
FROM person p
INNER JOIN review r ON r.person_id = p.id
GROUP BY p.id;
Result :

Query Data from multiple sql tables

I have an ERD above. I want to get the price of the room based on channel and also the status (isInvisible) of the hotel that owns the room mentioned.
Also a RESTful-API endpoint for that, I tried many times on this assignment and can't get it right as I use Nodejs to write an API GET /api/${roomId}/price but the query doesn't work:
SELECT RoomPrice.price, Status.isInvisible
FROM RoomPrice
INNER JOIN Status
ON (RoomPrice.RoomID = Room.Id AND RoomPrice.ChannelID = ChannelId)
AND (Status.HotelID = Hotels.ID AND Status.ChannelID = ChannelID)
I use query below to create my database in WorkBench:
DROP TABLE IF EXISTS `address`;
CREATE TABLE `address` (
`id` int(9) unsigned NOT NULL AUTO_INCREMENT,
`hotel_id` int(9) unsigned NOT NULL,
`address` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY(hotel_id) REFERENCES hotels(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `address` (`hotel_id`, `address`)
VALUES
(1, '7008 Lynch Centers Apt. 596\nLysannemouth, RI 43355'),
(2, '04795 Stanley Mount Apt. 114\nDorrisborough, DC 38070-3542'),
(1, '24586 Eliseo Haven Suite 045\nKossville, WY 17890-7936'),
(2, '639 Toy Corners\nBashirianfort, CA 08964-7258');
DROP TABLE IF EXISTS `channels`;
CREATE TABLE `channels` (
`id` int(9) unsigned NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `channels` (`id`, `url`, `name`)
VALUES
(1, 'http://www.beahan.com/', 'quod'),
(2, 'http://www.douglas.com/', 'sit');
DROP TABLE IF EXISTS `hotels`;
CREATE TABLE `hotels` (
`id` int(9) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `hotels` (`id`, `name`)
VALUES
(1, 'illum'),
(2, 'aliquid');
DROP TABLE IF EXISTS `rooms`;
CREATE TABLE `rooms` (
`id` int(9) unsigned NOT NULL AUTO_INCREMENT,
`hotel_id` int(9) unsigned NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY(hotel_id) REFERENCES hotels(id)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
INSERT INTO `rooms` (`id`, `hotel_id`, `name`)
VALUES
(1, 1, 'vel'),
(2, 2, 'fugit'),
(3, 1, 'doloribus'),
(4, 2, 'ut'),
(5, 1, 'et');
DROP TABLE IF EXISTS `room_prices`;
CREATE TABLE `room_prices` (
`room_id` int(9) unsigned NOT NULL,
`channel_id` int(9) unsigned NOT NULL,
`price` decimal(10,2) NOT NULL,
PRIMARY KEY (room_id, channel_id),
FOREIGN KEY(room_id) REFERENCES rooms(id),
FOREIGN KEY(channel_id) REFERENCES channels(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `room_prices` (`room_id`, `channel_id`, `price`)
VALUES
(1, 1, '50687.86'),
(1, 2, '6687.86'),
(2, 1, '10687.86'),
(2, 2, '274739.20'),
(3, 1, '3828.63'),
(3, 2, '12525.86'),
(4, 1, '2623587.86'),
(4, 2, '125151.00'),
(5, 1, '2358704.85'),
(5, 2, '7347473.86');
DROP TABLE IF EXISTS `status`;
CREATE TABLE `status` (
`hotel_id` int(9) unsigned NOT NULL,
`channel_id` int(9) unsigned NOT NULL,
`isInvisible` BOOLEAN NOT NULL,
PRIMARY KEY (hotel_id, channel_id),
FOREIGN KEY(hotel_id) REFERENCES hotels(id),
FOREIGN KEY(channel_id) REFERENCES channels(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `status` (`hotel_id`, `channel_id`, `isInvisible`)
VALUES
(1, 1, false),
(2, 1, true),
(1, 2, true),
(2, 2, true);
I want that once I query to search for the price of roomId (i.e 1) it returns 2 rows (as the mock data only have 2 rows in channels table) that show:
room_id channel_id price isInvisible
1 1 xxxx.xx 0
1 2 xxxx.xx 1
At this moment, I use the query as DRapp help
SELECT
rp.room_id,
rp.channel_id,
rp.price,
s.isInvisible
FROM
room_prices rp
JOIN status s
ON (rp.channel_id = s.channel_id)
JOIN rooms r
ON (rp.room_id = r.id)
JOIN hotels h
ON (r.hotel_id = h.id)
WHERE rp.room_id = 1
It returns 4 rows (instead of 2 rows as expected)
room_id channel_id price isInvisible
1 1 xxxx.xx 0
1 2 xxxx.xx 1
1 1 xxxx.xx 1
1 2 xxxx.xx 1
You need to identify each of the relations as your ERD shows. Each table is joined to its respective context. Dont jump/skip. The only time you can in this scenario is to skip through the channels since the RoomPrice and Status table EACH have a "ChannelId" to qualify the join
SELECT
rp.price,
s.isInvisible
FROM
Room_Prices rp
JOIN Rooms r
on rp.room_id = r.id
JOIN Status s
ON rp.Channel_ID = s.Channel_Id
AND r.hotel_id = s.hotel_id
WHERE
rp.room_id = 1
I had to revise the query. I looked deeper and noticed your CHANNEL table ALSO had the Hotel, so I had to go from the room prices to the room table. From the room table, I can get the hotel. Now that I have the channel from room prices, AND the hotel ID from the rooms table. So NOW I join to the status table on BOTH columns getting the expected single row per room you are expecting.

Issues in import sql in phpmyadmin

While importing the sql data, it shows syntax error:
Here is my code:
CREATE TABLE IF NOT EXISTS `tblproduct` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`code` varchar(255) NOT NULL,
`image` text NOT NULL,
`price` double(10,2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `product_code` (`code`)
)
INSERT INTO `tblproduct` (`id`, `name`, `code`, `image`, `price`) VALUES
(1, '3D Camera', '3DcAM01', 'product-images/camera.jpg', 1500.00),
(2, 'External Hard Drive', 'USB02', 'product-images/external-hard-drive.jpg', 800.00),
(3, 'Wrist Watch', 'wristWear03', 'product-images/watch.jpg', 300.00);
I just confused with this, what is the exact error.
Can anyone help me to fix this? thanks in advance.
Looks like it's whole generated so there should be no errors. Try to add semicolon after create table syntax so each query is separated. Like this:
CREATE TABLE IF NOT EXISTS `tblproduct` (
`id` int(8) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`code` varchar(255) NOT NULL,
`image` text NOT NULL,
`price` double(10,2) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `product_code` (`code`)
);
INSERT INTO `tblproduct` (`id`, `name`, `code`, `image`, `price`) VALUES
(1, '3D Camera', '3DcAM01', 'product-images/camera.jpg', 1500.00),
(2, 'External Hard Drive', 'USB02', 'product-images/external-hard-drive.jpg', 800.00),
(3, 'Wrist Watch', 'wristWear03', 'product-images/watch.jpg', 300.00);

MySQL joining 2 tables in to one main table

I have 2 tables 'cat' and 'sub_cat' and these two tables should join or something with main table 'product'
I tried all joining methods and non of them gave me right result I want.
I'm sure there is a method. I don't know what to call.
Sample SQL
This is how the last query should be
forget about the normalization theories and every thing and I just want the last query to be like this or mysql method that I can use on this.
cat_id cannot be duplicate
s_id should also cannot be duplicate
like in third row there can be: cat_id but no s_id the s_id should be null
if there is no cat_id and no s_id both should be null like fourth row
p_id can be duplicate
can't use group by or distinct cause it doesn't give null values then as i know
only method i got closer is using left joining both cat and sub_cat to prod table but it gives me duplicate cat_id and s_id and can't use group by or distinct on this cause there should be null values.
here is the test data
CREATE TABLE IF NOT EXISTS `cat` (
`product_id` int(11) DEFAULT NULL,
`cat_id` int(11) DEFAULT NULL,
`cat_name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `cat` (`product_id`, `cat_id`, `cat_name`) VALUES
(1, 1, 'cat1'),
(2, 2, 'cat2'),
(3, 3, 'cat3'),
(1, 4, 'ca4');
CREATE TABLE IF NOT EXISTS `prod` (
`product_id` int(11) DEFAULT NULL,
`name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `prod` (`product_id`, `name`) VALUES
(1, 'prod1'),
(2, 'prod2'),
(3, 'pro3'),
(4, 'prod4');
CREATE TABLE IF NOT EXISTS `sub_cat` (
`product_id` int(11) DEFAULT NULL,
`sub_cat_id` int(11) DEFAULT NULL,
`sub_cat_name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `sub_cat` (`product_id`, `sub_cat_id`, `sub_cat_name`) VALUES
(1, 1, 'sub cat 1'),
(2, 2, 'sub cat 2'),
(1, 3, 'sub3');
I have done a similar thing in this one.prop_cat acts as you Category table,prop_subcat as your subcategory table and property as you product.
CREATE TABLE `prop_cat` (
`pcat_id` int(11) NOT NULL AUTO_INCREMENT,
`pcat_name` varchar(60) DEFAULT NULL,
PRIMARY KEY (`pcat_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE `prop_subcat` (
`psubcat_id` int(11) NOT NULL,
`pcat_id` int(11) NOT NULL,
`psubcat_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`psubcat_id`,`pcat_id`),
KEY `pspc_idx` (`pcat_id`),
CONSTRAINT `catsub` FOREIGN KEY (`pcat_id`) REFERENCES `prop_cat` (`pcat_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `property` (
`prop_id` int(11) NOT NULL AUTO_INCREMENT,
`prop_name` varchar(25) DEFAULT NULL,
`price` double DEFAULT NULL,
`location` varchar(50) DEFAULT NULL,
`image` varchar(60) DEFAULT NULL,
`area` double DEFAULT NULL,
`psubcat_id` int(11) DEFAULT NULL,
`description` text,
PRIMARY KEY (`prop_id`),
KEY `psub_idx` (`psubcat_id`),
CONSTRAINT `psub` FOREIGN KEY (`psubcat_id`) REFERENCES `prop_subcat` (`pcat_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
SELECT
prop_cat.`pcat_id` AS prop_cat_pcat_id,
prop_cat.`pcat_name` AS prop_cat_pcat_name,
prop_subcat.`psubcat_id` AS prop_subcat_psubcat_id,
prop_subcat.`pcat_id` AS prop_subcat_pcat_id,
prop_subcat.`psubcat_name` AS prop_subcat_psubcat_name,
property.`prop_id` AS property_prop_id,
property.`prop_name` AS property_prop_name,
property.`price` AS property_price,
property.`location` AS property_location,
property.`image` AS property_image,
property.`area` AS property_area,
property.`psubcat_id` AS property_psubcat_id,
property.`description` AS property_description
FROM
`prop_cat` prop_cat INNER JOIN `prop_subcat` prop_subcat ON prop_cat.`pcat_id` = prop_subcat.`pcat_id`
INNER JOIN `property` property ON prop_subcat.`pcat_id` = property.`psubcat_id`

Find all missing mapping table entries

I need to be able to determine all of the people that were missing from attendance in a series of meetings.
I have a solution to figure this problem out with JS on the client's computer but I think it could be done more efficiently on the server.
Table A (people) -> Table B (attendance) <- Table C(meeting)
The attendance is a mapping table of items in table A and C.
See: http://sqlfiddle.com/#!8/6db81 for the exact schema
What I want is to determine all of the meetings that people have missed. That is there is no entry for that person for that meeting in the attendance table B.
Desired output should include a minimum of the lid (user id) and mid (meeting ID).
lid, firstname, lastname, mid, meeting_title, start.
The solution in JS would be to send the results of a cross of A and C, and the results of B to the client. Then remove all of the items in B from the cross of A and C.
CREATE TABLE IF NOT EXISTS `attendance` (
`mid` bigint(20) NOT NULL,
`sid` bigint(20) DEFAULT NULL,
`entered` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`lid` varchar(64) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`mid`,`lid`),
KEY `entered` (`entered`)
);
INSERT INTO `attendance` (`mid`, `sid`, `entered`, `lid`) VALUES
(5, NULL, '2013-12-25 21:44:27', '100'),
(5, NULL, '2013-12-25 21:44:19', '200'),
(5, NULL, '2013-12-25 21:44:21', '300'),
(9, NULL, '2013-12-26 14:49:49', '200'),
(9, NULL, '2013-12-26 07:10:34', '300');
CREATE TABLE IF NOT EXISTS `meetings` (
`mid` bigint(11) NOT NULL AUTO_INCREMENT,
`title` varchar(32) CHARACTER SET utf8 NOT NULL,
`start` datetime NOT NULL COMMENT 'registration start time',
`stop` datetime NOT NULL COMMENT 'registration stop time',
PRIMARY KEY (`mid`),
UNIQUE KEY `title` (`title`)
);
INSERT INTO `meetings` (`mid`, `title`, `start`, `stop`) VALUES
(5, 'Meeting 1', '2013-12-25 01:12:00', '2013-12-25 23:12:00'),
(9, 'Meeting 2', '2013-12-26 01:00:00', '2013-12-26 23:00:00');
CREATE TABLE IF NOT EXISTS `people` (
`sid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`lid` varchar(64) NOT NULL,
`firstname` varchar(64) NOT NULL,
`lastname` varchar(64) NOT NULL,
`title` varchar(5) DEFAULT NULL,
`address` varchar(128) DEFAULT NULL,
`city` varchar(64) DEFAULT NULL,
`state` varchar(2) DEFAULT NULL,
`zip` varchar(9) DEFAULT NULL,
`phone` varchar(12) DEFAULT NULL,
`cell` varchar(12) DEFAULT NULL,
`email` varchar(64) DEFAULT NULL,
PRIMARY KEY (`sid`),
UNIQUE KEY `sid` (`sid`),
UNIQUE KEY `lid` (`lid`)
);
INSERT INTO `people` (`sid`, `lid`, `firstname`, `lastname`, `title`, `address`, `city`, `state`, `zip`, `phone`, `cell`, `email`) VALUES
(1, '100', 'Fred', 'Jones', 'Mr.', 'Somewhere', 'City', 'AK', '12345', '123-123-1234', '123-123-1234', 'email#email.com'),
(2, '200', 'Wilma', 'Jones', 'Mrs.', '', 'City', '', '12346', '', NULL, '');
You have to join people and meetings table to get all possible combinations of meeting id and userid and then filter out only those, which are not present in attendance table.
SELECT a.lid,
b.mid
FROM people a
CROSS JOIN meetings b
WHERE NOT EXISTS (SELECT 1
FROM attendance c
WHERE c.mid = b.mid
AND c.lid = a.lid);
Fiddle