Get same IDs from Detail Table - mysql

I have 2 tables in my mysql database:
CREATE TABLE IF NOT EXISTS `RECIPES` (
`recipes_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(50) COLLATE utf8_bin NOT NULL,
`text` varchar(2000) COLLATE utf8_bin NOT NULL,
`count_persons` int(11) NOT NULL,
`duration` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`date` datetime NOT NULL,
`accepted` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`recipes_id`),
KEY `recipes_user_fk` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=88 ;
CREATE TABLE IF NOT EXISTS `RECIPES_POS` (
`recipes_pos_id` int(11) NOT NULL AUTO_INCREMENT,
`recipes_id` int(11) NOT NULL,
`ingredients_id` int(11) NOT NULL,
`ingredients_value` int(11) NOT NULL,
PRIMARY KEY (`recipes_pos_id`),
KEY `recipe_pos_rec_id` (`recipes_id`),
KEY `recipes_pos_ingredient_fk` (`ingredients_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=58 ;
In the Recipe_Pos Table are many entries. This table shows what ingredients are used in the Recipe.
Now i want to find the recipe which contains incredients like powder and sugar:
SELECT r.recipes_id FROM RECIPES r, RECIPES_POS rp WHERE r.recipes_id = rp.recipes_id AND rp.ingredients_id =6 AND rp.ingredients_id =4
this statment is wrong because a entry in Recipe_Pos can'T contains both incredients.
Whats the right query? It should works with only 1 incredient and more

select r.recipes_id
from RECIPES r
inner join RECIPES_POS rp on r.recipes_id = rp.recipes_id
where rp.ingredients_id in (4, 6)
group by r.recipes_id
having count(distinct rp.ingredients_id) = 2

Related

MySql Using filesort when i using a group by

I have a little problem with optimizing a query, I have 2 tables, one which records the participation (participation) in a quiz, and the other which records the answer to each question (participation_rep), participation is linked to the campaign table.
SELECT count(DISTINCT p.id) as number_of_participation
FROM participation_rep prep
INNER JOIN participation p
ON p.id = prep.id_participation
AND p.trash <> 1
WHERE prep.id_question IN (780,787,794,801,809)
AND prep.trash <> 1
GROUP BY pp.id_campaign
Explain of the query
And the problem is that this request is very heavy to execute when there is a lot of data which is concerned by the request and I do not know how to optimize it.
This query take 30-50ms to execute.
Structure of table participation :
CREATE TABLE IF NOT EXISTS `participation` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_campagne` int(11) NOT NULL,
`id_identifiant` int(11) DEFAULT NULL,
`firstname` varchar(255) DEFAULT NULL,
`surname` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`date_p` date NOT NULL,
`hour_p` time NOT NULL,
`comment` text,
`trash` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Structure of table participation_rep :
CREATE TABLE IF NOT EXISTS `participation_rep` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_participation` int(11) NOT NULL,
`id_question` int(11) NOT NULL,
`id_rep` int(11) NOT NULL,
`trash` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `id_participation` (`id_participation`,`id_question`,`id_reponse`),
KEY `id_question` (`id_question`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Spped up MySQL query

I need help speeding up a MySQL query that's running extremely slowly. It's taking over 35 seconds to return 900 rows.
Does anyone have ideas how I can speed things up on this query?
Many thanks in advance
select products.*,
p.price as lowest_price,
products_images.thumbnail
from products
inner join products_categories on products_categories.product_id = products.id
inner join products_colours on products_colours.product_id = products.id
inner join products_quantity_pricing on products_quantity_pricing.product_id = products.id
left join ( select min(price) as price, product_id from products_quantity_pricing group by products_quantity_pricing.product_id ) as p on p.product_id = products.id
inner join products_images on products_images.product_id = products.id
where products.id > 0 group by products.id
order by products.product_name
Here is the setup of the tables involved:
CREATE TABLE IF NOT EXISTS `products_categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` smallint(5) unsigned zerofill NOT NULL,
`category` int(11) NOT NULL,
`sub_category` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1016 ;
CREATE TABLE IF NOT EXISTS `products` (
`product_prefix` varchar(10) NOT NULL,
`id` smallint(5) unsigned zerofill NOT NULL AUTO_INCREMENT,
`supplier_id` int(11) NOT NULL,
`product_code` varchar(50) NOT NULL,
`supplier_product_code` mediumtext NOT NULL,
`product_name` varchar(200) NOT NULL,
`product_description` text NOT NULL,
`print_area` varchar(100) DEFAULT NULL,
`print_position` varchar(100) DEFAULT NULL,
`dimensions` varchar(100) DEFAULT NULL,
`origination` tinytext,
`unit_cost` decimal(9,2) NOT NULL,
`updated` datetime NOT NULL,
`url` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `product_code` (`product_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=901 ;
CREATE TABLE IF NOT EXISTS `products_images` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` smallint(5) unsigned zerofill NOT NULL,
`fullsize` varchar(255) NOT NULL,
`midsize` varchar(255) NOT NULL,
`thumbnail` varchar(255) NOT NULL,
`updated` datetime NOT NULL,
`colour_tag` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2402 ;
CREATE TABLE IF NOT EXISTS `products_colours` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` smallint(5) unsigned zerofill NOT NULL,
`colour` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
KEY `product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2546 ;
CREATE TABLE IF NOT EXISTS `products_quantity_pricing` (
`product_id` smallint(5) unsigned zerofill NOT NULL,
`quantity` smallint(6) NOT NULL,
`price` decimal(9,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Add indexes on the product_id columns in all the tables.
In the products_quantity_pricing, a composite index on (product_id, price) will also speed up finding the minimum price for each product. If you create this composite index, you don't need to create a separate index just on product_id; the prefix of a composite index also serves as an index of its own.

MySQL: Find "last modified" date from two tables

I have two MySQL tables: tech_requests and comments. I want to display each tech_request one time in a list ordered by the "last modified" date, whether that be the date of the tech_request creation or the latest comment tied to that tech_request. I was trying to use UNION but I got stuck. Any ideas would be much appreciated. Here are the tables:
CREATE TABLE `tech_requests` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`staff_member_id` int(3) NOT NULL,
`date_time` datetime NOT NULL,
`request` text NOT NULL,
`building_id` int(2) NOT NULL,
`technician_id` int(2) DEFAULT NULL,
`completed` tinyint(1) NOT NULL,
`subject` varchar(30) NOT NULL DEFAULT '',
`category_id` int(2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=203 DEFAULT CHARSET=utf8;
CREATE TABLE `comments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tech_request_id` int(11) NOT NULL,
`technician_id` int(2) NOT NULL,
`date_time` datetime NOT NULL,
`comment` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=234 DEFAULT CHARSET=utf8;
Are you looking for something like this?
SELECT r.id, r.staff_member_id, ...,
GREATEST(r.date_time, COALESCE(c.date_time, 0)) last_modified
FROM tech_requests r LEFT JOIN
(
SELECT tech_request_id, MAX(date_time) date_time
FROM comments c
GROUP BY tech_request_id
) c
ON r.id = c.tech_request_id
ORDER BY last_modified
Here is SQLFiddle demo

SQL query; inner join on 4 tables

Is this the most efficient way of joining these 4 tables? Also is it possible to only have some rows of each tables selected? I tried changing * to a name of a column but only the columns from studentlist are allowed.
SELECT c.classID, c.instrument, c.grade, u.ID, u.firstname, u.lastname, u.lastsongplayed, u.title
FROM studentlist s
INNER JOIN classlist c ON s.listID = c.classID
INNER JOIN (
SELECT *
FROM users u
INNER JOIN library l ON u.lastsongplayed = l.fileID
)
u ON s.studentID = u.ID
WHERE teacherID =3
ORDER BY classID
LIMIT 0 , 30
Database structure:
CREATE TABLE IF NOT EXISTS `classlist` (
`classID` int(11) NOT NULL AUTO_INCREMENT,
`teacherID` int(11) NOT NULL,
`instrument` text,
`grade` int(11) DEFAULT NULL,
PRIMARY KEY (`classID`),
KEY `teacherID_2` (`teacherID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=27 ;
CREATE TABLE IF NOT EXISTS `studentlist` (
`listID` int(11) NOT NULL,
`studentID` int(11) NOT NULL,
KEY `teacherID` (`studentID`),
KEY `studentID` (`studentID`),
KEY `listID` (`listID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `users` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(60) NOT NULL,
`password` varchar(60) NOT NULL,
`firstname` text NOT NULL,
`lastname` text NOT NULL,
`sessionID` varchar(60) DEFAULT NULL,
`lastlogin` time DEFAULT NULL,
`registerdate` date NOT NULL,
`isteacher` tinyint(1) DEFAULT NULL,
`isstudent` tinyint(1) DEFAULT NULL,
`iscomposer` tinyint(1) DEFAULT NULL,
`lastsongplayed` int(11) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `ID` (`ID`),
UNIQUE KEY `email` (`email`,`sessionID`),
KEY `ID_2` (`ID`),
KEY `ID_3` (`ID`),
KEY `lastsongplayed` (`lastsongplayed`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=63 ;
CREATE TABLE IF NOT EXISTS `library` (
`fileID` int(11) NOT NULL AUTO_INCREMENT,
`userID` int(11) NOT NULL,
`uploaddate` datetime NOT NULL,
`title` varchar(60) NOT NULL,
`OrigComposer` varchar(60) NOT NULL,
`composer` varchar(60) NOT NULL,
`genre` varchar(60) DEFAULT NULL,
`year` year(4) DEFAULT NULL,
`arrangement` varchar(60) DEFAULT NULL,
PRIMARY KEY (`fileID`),
KEY `userID` (`userID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=77 ;
Is this the most efficient way of joining these 3 tables?
Your JOIN looks correct and you are joining on your keys. So this should be efficient. However, I would encourage you to analyze your query with EXPLAIN to determine additional optimizations.
Is it possible to only have some rows of each tables selected?
Yes. Change * to be the columns from each table you want. I encourage you to explicitly prefix them with the originating table. Depending on the columns you select, this could also make your query more performant.
SELECT studentlist.studentID, users.email FROM ...

MySQL query: Get all album covers

I need some help formulating this query. I have two (relevant) tables, which I will dump here for reference:
CREATE TABLE IF NOT EXISTS `albums` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT 'owns all photos in album',
`parent_id` int(11) DEFAULT NULL,
`left_val` int(11) NOT NULL,
`right_val` int(11) NOT NULL,
`name` varchar(80) COLLATE utf8_unicode_ci NOT NULL,
`num_photos` int(11) NOT NULL,
`date_created` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `parent_id` (`parent_id`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;
CREATE TABLE IF NOT EXISTS `photos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`album_id` int(11) NOT NULL,
`filename` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
`num_views` int(11) NOT NULL DEFAULT '0',
`date_uploaded` int(11) NOT NULL,
`visibility` enum('friends','selected','private') COLLATE utf8_unicode_ci NOT NULL,
`position` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=26 ;
Now I want to grab the first photo (lowest position #) from each album owned by a certain user.
Here's what I'm trying:
SELECT * FROM albums JOIN photos ON photos.album_id=albums.id WHERE albums.user_id=%s GROUP BY album_id HAVING min(position)
But the having clause doesn't seem to have an effect. What's the problem?
select * from album, photos
where album_id=albums.id
and albums.user_id='user_id'
and photos.id = (select id from photos where
album_id = album.id order by position LIMIT 1)
You could use ORDER BY and LIMIT your results to the first row like so:
SELECT photos.*
FROM
albums, photos
WHERE
photos.album_id=albums.id
AND albums.user_id=%s
ORDER BY
photos.position ASC
LIMIT 1