Optimise DISTINCT . in mysql from a large Mysql table - mysql

I have a problem with a query, It make more than 1 minutes and I think the problem come from my distinct
My index:
table1 (project_name)
table2 (importer_id,sipplier_id)
table3 (name)
My table 2 have more than 2 millions rows
Here my query
SELECT DISTINCT table1.id AS project_id,
table1.name AS project_name,
table3.id AS supplier_id,
table4.report_id as report_id,
table3.name AS supplier_name
FROM table1
LEFT JOIN table2 ON table2.project_id = table1.id
LEFT JOIN table3 ON table3.id = table2.supplier_id
LEFT JOIN table4 ON table4.project_id = table1.id
WHERE table1.id IN
('2067', '2068', '2069', '2070', '2072', '2073', '2074', '2083', '2084', '2085', '2086', '2087', '2088', '2089',
'2090', '2091', '2092', '2093', '2094', '2095', '2096', '2097', '2098', '2100', '2101', '2102', '2103', '2104',
'2105', '2106', '2107', '2108', '2109', '2110', '2111', '2112', '2113', '2114', '2115', '2116', '2117', '2118',
'2119', '2120', '2121', '2122', '2123', '2124', '2125', '2126', '2127')
AND (table2.importer_id IN ('215') OR table2.supplier_id IN ('215'))
Create table statement for all tables (table 1 table 2 table 3 table 4)
CREATE TABLE `table1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`client_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_wsxix_projects` (`client_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2085 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `table2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`buyer_id` int(11) unsigned DEFAULT NULL,
`client_id` int(11) unsigned DEFAULT NULL,
`merchandiser_user_id` int(11) unsigned DEFAULT NULL,
`factory_id` int(11) unsigned DEFAULT NULL,
`dc_id` int(11) unsigned DEFAULT NULL,
`parent_id` int(10) unsigned DEFAULT NULL,
`supplier_id` int(11) unsigned NOT NULL,
`importer_id` int(11) unsigned NOT NULL,
`project_id` int(11) unsigned NOT NULL,
`tier_two_id` int(11) unsigned DEFAULT NULL,
`store_id` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `buyer_id` (`buyer_id`),
KEY `client_id` (`client_id`),
KEY `merchandiser_user_id` (`merchandiser_user_id`),
KEY `FK_po_factory_companies_id` (`factory_id`),
KEY `FK_po_dc_companies_id` (`dc_id`),
KEY `index_po_parentid` (`parent_id`),
KEY `index_purchaseorders_cie` (`supplier_id`),
KEY `index_poimporter_cie` (`importer_id`),
KEY `index_purchaseorders_project` (`project_id`),
KEY `facory_importer_id` (`factory_id`,`importer_id`),
KEY `posu` (`project_id`,`supplier_id`),
KEY `store_id` (`store_id`),
KEY `tier_two_id` (`tier_two_id`)
) ENGINE=InnoDB AUTO_INCREMENT=34959 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `table3` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent_company_id` int(11) DEFAULT NULL,
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`type_id` int(11) unsigned DEFAULT NULL,
`description` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`use_majora_majorb` tinyint(1) NOT NULL DEFAULT '0',
`aql_presets_id` int(11) unsigned DEFAULT NULL,
`fabx_presets_id` int(11) unsigned DEFAULT NULL,
`group_id` int(11) unsigned DEFAULT NULL,
`contact_number` varchar(55) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`unit_number` varchar(55) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`use_factory_location` tinyint(1) unsigned DEFAULT NULL,
`restrict_users_access_to_sub_companies` tinyint(1) unsigned DEFAULT '0' COMMENT 'Using for share function so far',
PRIMARY KEY (`id`),
KEY `index_wsxix_companies_aql_presets_id` (`aql_presets_id`),
KEY `index_company_type` (`type_id`),
KEY `index_companies_group_id` (`group_id`),
KEY `fk_wsxix_companies_fabx_presets_idx` (`fabx_presets_id`)
) ENGINE=InnoDB AUTO_INCREMENT=992 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `table4` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`report_id` int(11) NOT NULL,
`project_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `index_project_reports_projects` (`project_id`),
KEY `index_project_reports_reports` (`report_id`),
CONSTRAINT `fk_project_reports_projects` FOREIGN KEY (`project_id`) REFERENCES `wsxix_projects` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_project_reports_reports` FOREIGN KEY (`report_id`) REFERENCES `wsxix_report_types` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=138 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Alright, here is my first attempt. Keep in mind that this is a rather difficult query to optimize, given all the OR and IN statements.
Try the following rewritten query. It uses a semi-join to avoid the need for DISTINCT, which may result in a decent performance improvement.
SELECT
table1.id AS project_id,
table1.name AS project_name,
table3.id AS supplier_id,
table4.report_id AS report_id,
table3.name AS supplier_name
FROM table1
LEFT OUTER JOIN table3
ON EXISTS (
SELECT 1 FROM table2
WHERE table2.project_id = table1.id
AND table2.supplier_id = table3.id
AND (table2.importer_id IN ('215') OR table2.supplier_id IN ('215'))
)
LEFT OUTER JOIN table4
ON table4.project_id = table1.id
WHERE table1.id IN
('2067', '2068', '2069', '2070', '2072', '2073', '2074', '2083', '2084', '2085', '2086', '2087', '2088', '2089',
'2090', '2091', '2092', '2093', '2094', '2095', '2096', '2097', '2098', '2100', '2101', '2102', '2103', '2104',
'2105', '2106', '2107', '2108', '2109', '2110', '2111', '2112', '2113', '2114', '2115', '2116', '2117', '2118',
'2119', '2120', '2121', '2122', '2123', '2124', '2125', '2126', '2127')
Then, add the following indexes, which should help performance as well:
ALTER TABLE table4
ADD INDEX sowr1 (project_id,report_id)
ALTER TABLE table2
ADD INDEX sowr2 (project_id,supplier_id,importer_id)
Run the query at least twice, and ignore the timing on the first run, so you can avoid the InnoDB buffer cache from giving inaccurate speed results.
Let me know how fast it runs. Then, if it still needs more improvement, provide the EXPLAIN plan for this query, as without your data at hand it is difficult to see exactly how well these changes will work.

Related

MYSQL, slow performance group by with multiples tables with millions rows

I have three table with more than 1 millions of rows and one of my query take more than 30 seconds with a date range of 3 months. I have tried multiples index and I think I have respect index orders. I don't know what to do go get a better performance.
Here my query, create table statement, in my explain
SELECT
MAX(table2.id) as item_id,
MAX(table2.sampled_inspected) as sample_size,
table1.group_col AS ass_group_id
FROM
table1
INNER JOIN table2 ON table1.id = table2.assignment_id
LEFT OUTER JOIN table3 ON table1.po_id = table3.id
LEFT JOIN table4 ON table4.id = table3.supplier_id
LEFT JOIN table5 ON table5.id = table3.project_id
WHERE table1.recycled=0
AND table2.inspection_status_id > 0
AND table2.inspection_status_id != 50
AND table3.importer_id = 215 AND table5.recycled = 0 AND table3.project_id IN ( '2062','2063','2064','2065' ) AND table2.inspection_completed_date >= DATE('2019-10-01') AND table2.inspection_completed_date <= DATE('2020-01-29')
GROUP BY ass_group_id
and here my 5 tables
CREATE TABLE `table1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`recycled` int(1) NOT NULL DEFAULT '0',
`group_col` varchar(25) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`po_id` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_assignment_po` (`po_id`),
KEY `recycled` (`recycled`,`group_col`),
KEY `group_col` (`group_col`)
) ENGINE=InnoDB AUTO_INCREMENT=3324705 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `table2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`assignment_id` int(10) unsigned DEFAULT NULL,
`sampling_size` int(11) DEFAULT NULL,
`notes` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`photo_report` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`inspection_status_id` int(11) DEFAULT '0',
`inspection_result_id` int(1) NOT NULL DEFAULT '0',
`inspection_completed_date` datetime DEFAULT NULL,
`recycled` int(1) NOT NULL DEFAULT '0',
`qty_to_inspect` decimal(11,2) DEFAULT NULL,
`defect_rate` decimal(16,13) DEFAULT NULL,
`sampled_inspected` int(11) unsigned DEFAULT NULL,
`inspection_report_id` int(11) unsigned DEFAULT NULL,
`poline_id` int(11) unsigned DEFAULT NULL,
`item_status_id` int(11) NOT NULL DEFAULT '0',
`production_line` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_wsxix_assignments` (`assignment_id`),
KEY `index_inspection_report_reportid` (`inspection_report_id`),
KEY `index_ai_inspection_completed_date` (`inspection_completed_date`),
KEY `index_item_poline` (`poline_id`),
KEY `index_item_poline_assignment` (`poline_id`,`assignment_id`),
KEY `wsxix_assignments_items_inspection_status_id` (`inspection_status_id`),
KEY `wsxix_assignments_items_inspection_result_id` (`inspection_result_id`),
KEY `inspection_completed_date` (`inspection_completed_date`,`inspection_result_id`,`inspection_status_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3324705 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `table3` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`buyer_id` int(11) unsigned DEFAULT NULL,
`client_id` int(11) unsigned DEFAULT NULL,
`merchandiser_user_id` int(11) unsigned DEFAULT NULL,
`factory_id` int(11) unsigned DEFAULT NULL,
`dc_id` int(11) unsigned DEFAULT NULL,
`parent_id` int(10) unsigned DEFAULT NULL,
`supplier_id` int(11) unsigned NOT NULL,
`importer_id` int(11) unsigned NOT NULL,
`project_id` int(11) unsigned NOT NULL,
`tier_two_id` int(11) unsigned DEFAULT NULL,
`store_id` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `buyer_id` (`buyer_id`),
KEY `client_id` (`client_id`),
KEY `merchandiser_user_id` (`merchandiser_user_id`),
KEY `FK_po_factory_companies_id` (`factory_id`),
KEY `FK_po_dc_companies_id` (`dc_id`),
KEY `index_po_parentid` (`parent_id`),
KEY `index_purchaseorders_cie` (`supplier_id`),
KEY `index_poimporter_cie` (`importer_id`),
KEY `index_purchaseorders_project` (`project_id`),
KEY `facory_importer_id` (`factory_id`,`importer_id`),
KEY `posu` (`project_id`,`supplier_id`),
KEY `store_id` (`store_id`),
KEY `tier_two_id` (`tier_two_id`)
) ENGINE=InnoDB AUTO_INCREMENT=34959 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `table4` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent_company_id` int(11) DEFAULT NULL,
`name` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `parent_company_id` (`parent_company_id`)
) ENGINE=InnoDB AUTO_INCREMENT=272 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `table5` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`recycled` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `recycled` (`recycled`)
) ENGINE=InnoDB AUTO_INCREMENT=2066 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Add these indexes:
table2: (assignment_id, inspection_completed_date)
table2: (inspection_completed_date, assignment_id)
table3: (importer_id, project_id, supplier_id, id)
table3: (project_id, importer_id, supplier_id, id)
table5: (recycled, id)
table1: (recycled, po_id, id, group_col)
Remove this; it adds nothing, but slows down the query:
LEFT JOIN table4 ON table4.id = table3.supplier_id

Min, MAx SQL query optimization

I have the following query and I really need help optimizing it:
SELECT min(p.price) as min_price, max(p.price) as max_price
FROM product p
INNER JOIN product_category pc
ON p.id_product = pc.id_product AND
p.id_project = 1 AND
pc.id_category = 2 AND
p.active = 1
The tables are:
CREATE TABLE `product` (
`id_product` bigint(10) UNSIGNED NOT NULL,
`id_project` int(11) NOT NULL,
`reference` varchar(50) NOT NULL,
`reference_internal` varchar(125) NOT NULL,
`sku` varchar(50) NOT NULL,
`price` float(12,2) NOT NULL,
`old_price` float NOT NULL,
`reduction_amount` float NOT NULL,
`reduction_percent` float NOT NULL,
`is_reduced` int(1) NOT NULL,
`id_manufacturer` int(10) NOT NULL,
`id_supplier` int(10) NOT NULL,
`is_new` int(1) NOT NULL,
`popularity` int(1) NOT NULL,
`quantity` int(1) NOT NULL,
`active` int(1) NOT NULL,
`date_add` datetime NOT NULL,
`date_upd` datetime NOT NULL,
`id_category` int(11) NOT NULL,
`indexed` int(1) NOT NULL,
`id_color` int(13) NOT NULL,
`rating` int(1) NOT NULL,
`rating_count` int(11) NOT NULL,
`viewed` int(5) NOT NULL,
`a_id_product` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `product`
ADD PRIMARY KEY (`id_product`),
ADD KEY `id_product` (`id_product`),
ADD KEY `reference` (`reference`),
ADD KEY `reference_internal` (`reference_internal`),
ADD KEY `sku` (`sku`),
ADD KEY `reduction_amount` (`reduction_amount`),
ADD KEY `reduction_percent` (`reduction_percent`),
ADD KEY `is_reduced` (`is_reduced`),
ADD KEY `id_manufacturer` (`id_manufacturer`),
ADD KEY `id_supplier` (`id_supplier`),
ADD KEY `is_new` (`is_new`),
ADD KEY `popularity` (`popularity`),
ADD KEY `date_add` (`date_add`),
ADD KEY `date_upd` (`date_upd`),
ADD KEY `id_category` (`id_category`),
ADD KEY `indexed` (`indexed`),
ADD KEY `id_color` (`id_color`),
ADD KEY `price` (`price`),
ADD KEY `rating` (`rating`),
ADD KEY `a_id_product` (`a_id_product`),
ADD KEY `t7` (`price`,`id_product`,`id_project`,`active`) USING BTREE;
-- AUTO_INCREMENT for dumped tables
-- AUTO_INCREMENT for table `product`
ALTER TABLE `product`
MODIFY `id_product` bigint(10) UNSIGNED NOT NULL AUTO_INCREMENT;
COMMIT;
There product_categories table:
CREATE TABLE `product_category` (
`id_product` int(10) DEFAULT NULL,
`id_project` int(11) NOT NULL,
`id_category` int(5) NOT NULL,
`menu_order` int(5) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `product_category`
--
ALTER TABLE `product_category`
ADD KEY `id_product` (`id_product`),
ADD KEY `id_project` (`id_project`),
ADD KEY `id_category` (`id_category`),
ADD KEY `menu_order` (`menu_order`),
ADD KEY `t1` (`id_product`,`id_category`),
ADD KEY `t2` (`id_product`,`id_project`,`id_category`);
COMMIT;
The explain statement https://snag.gy/8ClFnh.jpg
I have 45 MS execution time but the database is not very large, i have around 20.000 products but when it's live i will have million of products and the 0.0550 seconds execution time seems very long for this number of products, anyone can help with an optimization suggestion?
I have mysql 5.7.
Your query should be pretty easy to optimize, if the number of rows you are selecting is low (0.5% or less of the total).
The indexes below should help:
create index ix1_product on product (id_project, active, price);
create index ix2_procat on product_category (id_product, id_category);

MySQL returns only one result

This is my product table:
CREATE TABLE `products` (
`idproduct` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`description` text NOT NULL,
`price` double unsigned NOT NULL,
`shipping` double unsigned DEFAULT NULL,
`condition` int(10) unsigned NOT NULL,
`returns` int(10) unsigned NOT NULL,
`date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`image` varchar(255) DEFAULT NULL,
PRIMARY KEY (`idproduct`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8
And this is my product_categories table
CREATE TABLE `products_subcategories` (
`idproduct_category` int(10) unsigned NOT NULL AUTO_INCREMENT,
`idproduct` int(10) unsigned NOT NULL,
`idsubcategory` int(10) unsigned NOT NULL,
PRIMARY KEY (`idproduct_category`),
KEY `products_categories_products_idx` (`idproduct`),
KEY `products_categories_categories_idx` (`idsubcategory`),
CONSTRAINT `products_subcategories_products` FOREIGN KEY (`idproduct`) REFERENCES `products` (`idproduct`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `products_subcategories_subcategories` FOREIGN KEY (`idsubcategory`) REFERENCES `subcategories` (`idSubcategory`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
I trying to search in products like that:
Select products.* from products
INNER JOIN products_subcategories
ON products.idproduct = products_subcategories.idproduct
WHERE name LIKE '%p%'
but it returns only one row.. without inner join it returns me more rows

fix Using index, Using temporary, Using filesort

i have such 3 tables. Im trying to Left Join them
SELECT `t`.`title` AS `category_title`,`t`.`id` AS `category_id`, `st`.`title` AS
`subcategory_title`, `st`.`id` AS `subcategory_id`, `st`.`parent_id` AS
`subcategory_parent`, `n`.`title` AS `news_title`,`n`.`id` AS `news_id` FROM
`t_categories` `t` LEFT JOIN t_categories AS `st` ON `st`.`parent_id`=t.`id` LEFT JOIN
t_newsrelations AS `nr` ON `nr`.`category_id`=st.`id` LEFT JOIN t_news AS `n` ON
`n`.`id`=nr.`news_id` WHERE `t`.`enabled` = 1 AND `n`.`enabled` = 1 AND `n`.`type`!=1 AND
`n`.`type`!=5 ORDER BY `t`.`position`,`st`.`position`,`n`.`position` ASC
here is the structure of tables
CREATE TABLE IF NOT EXISTS `t_categories` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL,
`title` tinytext NOT NULL,
`position` tinyint(4) unsigned NOT NULL DEFAULT '0',
`type` tinyint(1) unsigned NOT NULL,
`enabled` tinyint(1) unsigned NOT NULL DEFAULT '1',
UNIQUE KEY `id` (`id`),
KEY `type` (`type`),
KEY `parent_id` (`parent_id`),
KEY `enabled` (`enabled`),
KEY `id_parent_position_enabled` (`id`,`parent_id`,`position`,`enabled`),
KEY `position` (`position`),
KEY `parent_id_2` (`parent_id`,`enabled`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `t_news` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` tinytext NOT NULL,
`m_title` tinytext NOT NULL,
`url` varchar(2000) NOT NULL,
`keywords` text NOT NULL,
`description` text NOT NULL,
`body` longtext NOT NULL,
`position` tinyint(4) unsigned NOT NULL DEFAULT '0',
`type` tinyint(1) unsigned NOT NULL,
`city_id` int(4) NOT NULL,
`quickmenu_enabled` tinyint(1) unsigned NOT NULL DEFAULT '0',
`quickmenu` text NOT NULL,
`enabled` tinyint(1) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
KEY `position` (`position`),
KEY `type` (`type`),
KEY `city_id` (`city_id`),
KEY `url` (`url`(333)),
KEY `quickmenu_enabled` (`quickmenu_enabled`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `t_newsrelations` (
`category_id` int(11) NOT NULL,
`news_id` int(11) unsigned NOT NULL,
KEY `category_id` (`category_id`),
KEY `news_id` (`news_id`),
KEY `category_id_2` (`category_id`,`news_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
And SELECT EXPLAIN shows me
t_newsrelations is intermediate table. Table t_categories contains categories and subcategories linked by parent_id column. Each item from t_news can be a member of more than one subcategories thats why they linked through t_newsrelations
how to optimise a query? Why it shows Using index, Using temporary, Using filesort?
ORDER BY `t`.`position`,`st`.`position`,`n`.`position` ASC
You can't eliminate the temp table and filesort in this query, given the tables you have, because you're sorting on columns from multiple tables. Optimizing sorting means using an index so that the query fetches rows in the order you want them. But there's no way in MySQL to create an index that spans multiple tables.
The only way to fix this is to denormalize until all three columns are in a single table, and create one index over the three columns. But denormalization comes with its own downsides.

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 ...