Understanding MySql queries - mysql

Trying to teach my self a bit of mysql and php and decided to do that by working on actual project with help oh "how to do everything with MySQL and PHP book".
first problem i have is with understanding joint table queries.
here are my tables:
CREATE TABLE `clients` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
`client` VARCHAR(50) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `KlientID` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=8;
CREATE TABLE `facilities` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
`facility` VARCHAR(45) NOT NULL,
`fk_client` SMALLINT(6) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `fk_idklijent_idx` (`fk_client`),
CONSTRAINT `FK_client_id` FOREIGN KEY (`fk_client`) REFERENCES `clients` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=35;
CREATE TABLE `models` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
`model` VARCHAR(50) NOT NULL,
`fk_manufacturer` SMALLINT(6) NOT NULL,
PRIMARY KEY (`id`),
INDEX `ModelID` (`id`),
INDEX `fk_proizvodjacID_idx` (`fk_manufacturer`),
CONSTRAINT `FK_manuf_id` FOREIGN KEY (`fk_manufacturer`) REFERENCES `manufacturers` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=9;
CREATE TABLE `machines` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
`serial` VARCHAR(50) NOT NULL,
`fk_model` SMALLINT(6) NOT NULL,
`InvBr` INT(11) NULL DEFAULT '0',
`fk_facilities` SMALLINT(6) NULL DEFAULT '0',
`sw` VARCHAR(255) NULL DEFAULT NULL,
`adaptation` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `FK_uredjaji_modeli` (`fk_model`),
INDEX `FK_uredjaji_poslovnice` (`fk_facilities`),
INDEX `Index 4` (`serial`),
CONSTRAINT `FK_facility_id` FOREIGN KEY (`fk_facilities`) REFERENCES `facilities` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT `FK_models_id` FOREIGN KEY (`fk_model`) REFERENCES `models` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=93;
CREATE TABLE `technicians` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `ServiserID` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=5;
CREATE TABLE `workorders` (
`id` SMALLINT(6) NOT NULL AUTO_INCREMENT,
`wo_nr` VARCHAR(50) NOT NULL,
`fk_machine_id` SMALLINT(6) NOT NULL,
`fk_technitian_id` SMALLINT(6) NOT NULL,
`counter` INT(11) NOT NULL DEFAULT '0',
`service_date` DATE NOT NULL,
`description` LONGTEXT NOT NULL,
`work_hours` INT(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
INDEX `FK_rn_serviseri` (`fk_technitian_id`),
INDEX `FK_machines_id_idx` (`fk_machine_id`),
CONSTRAINT `FK_machines_id` FOREIGN KEY (`fk_machine_id`) REFERENCES `machines` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT `FK_technitian_id` FOREIGN KEY (`fk_technitian_id`) REFERENCES `technicians` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1393;
using this query i get each row 8 times.
SELECT DATE_FORMAT (w.service_date, '%d.%m.%Y'), f.facility, m.model, mc.serial, w.description, t.name
FROM workorders AS w, facilities AS f, models AS m, machines AS mc, technicians AS t
WHERE f.id = mc.fk_facilities AND w.fk_machine_id = mc.id AND w.fk_technitian_id = t.id AND w.service_date > '2009-12-31'
ORDER BY w.service_date DESC;
can someone pls point me to what i'm doing wrong. i only need rows from workorders table. other tables are here only to show real data not only id's - bad, not true :(
thx
edit 1:
i need a list of workorders. to explain my question little more here is how the result should look like:
[date][name of the facility the machine (fk_machine_id) belongs to][model of the machine (fk_machine_id)][serial number of the machine (fk_machine_id)][description from workorder][technician name (fk_technician_id)]
edit2:
here is the model image
i think my problem is in fact that to get the model i need to check with machines table first. Same thing with facility.

got it!
the problem was in one missing AND.
final SELECT looks like this:
SELECT DATE_FORMAT (w.service_date, '%d.%m.%Y') AS service_date, w.wo_nr, f.facility, m.model, mc.serial, FORMAT (w.counter, 0) AS Counter, w.description, t.name AS technician
FROM workorders AS w, technicians AS t, machines AS mc, models AS m, facilities AS f
WHERE mc.fk_facilities = f.id
AND w.fk_machine_id = mc.id
AND mc.fk_model = m.id
AND w.fk_technitian_id = t.id
AND w.service_date > '2009-12-31'
ORDER BY w.service_date DESC;
thx all. moving on to the next problem :)

to get only rows from workorders table use this query
SELECT w.*
FROM workorders AS w, facilities AS f, models AS m, machines AS mc, technicians AS t
WHERE f.id = mc.fk_facilities AND w.fk_machine_id = mc.id AND w.fk_technitian_id = t.id AND w.service_date > '2009-12-31'
ORDER BY w.service_date DESC;

You say you only want data from the workorders table. Then you don't need all the other joins.
SELECT * FROM workorders WHERE service_date > '2009-12-31'
Unless you need the columns in their tables as well.
Not too sure exactly what you require though.

Only put the columns you want returned in your results set in the SELECT section of your query. You can still include columns from other tables in your joins, they just won't be displayed. Also if you are getting multiple rows then either your data contains duplicates in which case you should look at your keys and constraints or you are missing one or more joins.

Would this work for you?
SELECT DISTINCT DATE_FORMAT (w.service_date, '%d.%m.%Y') as service_date,
f.facility, m.model, mc.serial, w.description, t.name
FROM workorders AS w, facilities AS f, models AS m, machines AS mc, technicians AS t
WHERE f.id = mc.fk_facilities
AND w.fk_machine_id = mc.id
AND w.fk_technitian_id = t.id
AND w.service_date > '2009-12-31'
ORDER BY w.service_date DESC;

Related

Laravel 9: Query Builder: Sub Query Problems

I always built my own frameworks, so I know a lot of raw php. I thought I would learn Laravel 9 and make my first Laravel application.
I have solved my SQL sub query problem, after 4 hours but surely there is a better way.
I have a single table connected to multiple tables via linking tables and foreign keys. For example :
CREATE TABLE `video` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` text NOT NULL,
`description` text,
`producer_id` int(11) DEFAULT NULL,
`production_date` date DEFAULT NULL,
`link` text,
`format` varchar(3) NOT NULL,
`resolution` text,
`local_filename` text,
`local_path` text,
`local_rating` tinyint(4) DEFAULT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `producer_id` (`producer_id`),
CONSTRAINT `video_ibfk_1` FOREIGN KEY (`producer_id`) REFERENCES `producer` (`id`) ON DELETE SET NULL ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=2623 DEFAULT CHARSET=latin1
connects to
CREATE TABLE `video_genre` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`video_id` int(11) NOT NULL,
`genre_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `video_id` (`video_id`),
KEY `genre_id` (`genre_id`),
CONSTRAINT `video_genre_ibfk_1` FOREIGN KEY (`video_id`) REFERENCES `video` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT `video_genre_ibfk_2` FOREIGN KEY (`genre_id`) REFERENCES `genre` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=38391 DEFAULT CHARSET=latin1
connects to
CREATE TABLE `genre` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` text NOT NULL,
`parent_id` int(11) DEFAULT NULL,
`pic_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `pic_id` (`pic_id`),
CONSTRAINT `genre_ibfk_1` FOREIGN KEY (`pic_id`) REFERENCES `pic` (`id`) ON DELETE SET NULL ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=297 DEFAULT CHARSET=latin1
I have tried to use the query builder engine and found it impossible to do the query :
SELECT video.id, video.title
FROM video JOIN (
SELECT video.id AS id, video.title, COUNT(genre.id) as genre_count
FROM video
INNER JOIN video_genre ON video.id = video_genre.video_id
INNER JOIN genre ON video_genre.genre_id = genre.id
WHERE genre.id IN (24,25)
GROUP BY video.id
) as temp_table ON video.id = temp_table.id
WHERE genre_count = 2;
as the sub query functions seems too limited : laravel doc
so with a sigh I resorted to raw sql in my controller :
$genres=implode(',',$genres=$request->post('g'));
$genres_count=count($request->post('g'));
$results = DB::select( DB::raw("
SELECT video.id, video.title
FROM video JOIN (
SELECT video.id AS id, video.title, COUNT(genre.id) as genre_count
FROM video
INNER JOIN video_genre ON video.id = video_genre.video_id
INNER JOIN genre ON video_genre.genre_id = genre.id
WHERE genre.id IN ($genres)
GROUP BY video.id
) as temp_table ON video.id = temp_table.id
WHERE genre_count = $genres_count"));
return view('genre.show',['videos'=>$results]);
I could not pass the variables to DB:select in array and using :vaiable_name, as they, I assume, get quoted or somehow mangled.
does someone know a better way, or the right way? Thank you experts in advance :)
footnote: Along the way while I was trying to use the query builder I lost an hour on using
->WhereIn('column_name',[1,2,3])->toSql();
returns sql string 'WHERE column_name IN (?,?,?)' within. However the query is as expected, it uses [1,2,3] not [?,?,?] as stated; This a bug?

How to use JOIN in advance MySQL query

So I have been struggling with this question for a while, and trying to figure out the best way to use JOIN to get the answer of finding the "CertCount" per planet. I know that it wants to have it GROUP BY planets, but I have no clue where planets comes from. Here is the question and code below:
Find the number of certifications held by people grouped by planet. This should have two columns the first, "name" will be the names of planets that have at least one certification. The second column should be "CertCount" and will be the number of certifications held by people from that planet for example if Lee is certified in "Viper" and "Mechanic" and Kara is certified in "Viper" and they are both from Caprica, then the "CertCount" for caprica should be 3:
CREATE TABLE `bsg_cert` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
CREATE TABLE `bsg_cert_people` (
`cid` int(11) NOT NULL DEFAULT '0',
`pid` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`cid`,`pid`),
KEY `pid` (`pid`),
CONSTRAINT `bsg_cert_people_ibfk_1` FOREIGN KEY (`cid`) REFERENCES `bsg_cert` (`id`),
CONSTRAINT `bsg_cert_people_ibfk_2` FOREIGN KEY (`pid`) REFERENCES `bsg_people` (`id`)
) ENGINE=InnoDB
CREATE TABLE `bsg_people` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`fname` varchar(255) NOT NULL,
`lname` varchar(255) DEFAULT NULL,
`homeworld` int(11) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `homeworld` (`homeworld`),
CONSTRAINT `bsg_people_ibfk_1` FOREIGN KEY (`homeworld`) REFERENCES `bsg_planets` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB
CREATE TABLE `bsg_planets` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`population` bigint(20) DEFAULT NULL,
`language` varchar(255) DEFAULT NULL,
`capital` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB
So for the moment: I have the following:
SELECT bsg_planets.name ,
COUNT(*) AS CertCount
FROM bsg_cert_people people_cert
I know that I am missing some code, but I'm not sure where to go from here, and could use a little nudge in the right direction.
You need to join the table according to their primary and foreign key and then do the GROUP BY
SELECT ps.id,
ps.name ,
COUNT(distinct *) AS CertCount
FROM bsg_cert_people cp
JOIN bsg_people pe ON cp.pid = pe.id
JOIN bsg_planets ps ON pe.homeworld = ps.id
GROUP BY ps.id, ps.name
All you need is to do inner join among all 3 tables based on common ids of tables and then group by with Planet id.
Following query should work:
SELECT ps.name ,
count(cert.cid) AS CertCount
FROM bsg_cert_people cert
JOIN bsg_people people ON cert.pid = people.id
JOIN bsg_planets planet ON people.homeworld = planet.id
GROUP BY plsnet.id
having count(distinct *) > 0;
Hope it helps!

MySQL Improve performance execution time

I am trying to improve performance of following query which took 93.2 sec to execute query below:
SELECT year(date), month(date), `country_name_name`,
CEIL(count(res.`user_xmpp_login`) /DAY(LAST_DAY(date))) as avgUser,
CEIL(count(res.user)/DAY(LAST_DAY(date))) as avgPurchase
FROM
( SELECT DATE(`user_registration_timestamp`) as date,
user_country,
NULL as user, `user_xmpp_login`
FROM users
WHERE `user_registration_timestamp` >= "2015-01-01 00:00:00"
AND `user_registration_timestamp` < "2016-01-01 00:00:00"
UNION ALL
SELECT DATE(`ts`) as date, user_country, user, NULL as `user_xmpp_login`
FROM purchase_log p
INNER JOIN users u ON u.`user_xmpp_login` = p.`user`
WHERE `ts` >= "2015-01-01 00:00:00"
AND `ts` < "2016-01-01 00:00:00"
AND result in ('ok', 'cancelled', 'pending')
) AS res
INNER JOIN countries c ON c.`country_id` = res.`user_country`
INNER JOIN country_names cn
ON (cn.`country_name_country` = c.`country_id`
AND cn.`country_name_language` = 'en')
GROUP BY 1,2,3
ORDER BY 4 DESC,5 DESC, 3 ASC;
Explain command shows:
And structure of each table is:
purchase table:
CREATE TABLE `purchase` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`result` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `iuser` (`user`),
) ENGINE=InnoDB AUTO_INCREMENT=12710221 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
users table:
CREATE TABLE `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_country` int(11) DEFAULT NULL,
`user_xmpp_login` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`user_registration_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_xmpp_login_UNIQUE` (`user_xmpp_login`),
KEY `user_country_FK` (`user_country`),
KEY `user_registration_timestamp` (`user_registration_timestamp`),
CONSTRAINT `users_country_FK` FOREIGN KEY (`user_country`)
REFERENCES `countries` (`country_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=33504745 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
countries table
CREATE TABLE `countries` (
`country_id` int(11) NOT NULL AUTO_INCREMENT,
`country_code` varchar(2) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`country_id`),
) ENGINE=InnoDB AUTO_INCREMENT=508 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
country names
CREATE TABLE `country_names` (
`country_name_id` int(11) NOT NULL AUTO_INCREMENT,
`country_name_country` int(11) NOT NULL,
`country_name_language` char(2) COLLATE utf8_unicode_ci NOT NULL,
`country_name_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`country_name_id`),
UNIQUE KEY `country_name_country_language_UNIQUE`
(`country_name_country`,`country_name_language`),
KEY `country_name_language` (`country_name_language`),
CONSTRAINT `country_name_country` FOREIGN KEY (`country_name_country`)
REFERENCES `countries` (`country_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=45793 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Is there any recommendations?
If you time each subquery, I think you will find users is the slowest component.
The purchase_log subquery can probably be improved with this "covering" INDEX(result, ts, user).
Combine the two "country" tables!. Use CHAR(2) CHARACTER SET ascii for the PRIMARY KEY and the JOINs to other tables. It is only 2 bytes, unlike INT, which is 4 bytes and VARCHAR..., which is 3 bytes (in this case).
You mention ts, but I don't see where it is coming from. If it is in purchase_log, then that table needs INDEX(user, ts).
What percentage of the users involved 2015? If it is more than about 20%, the INDEX(user_registration_timestamp) won't help.
Consider: Get rid of PRIMARY KEY (country_name_id), and promote the UNIQUE key to PRIMARY.
The biggest problem seems to be in your users table. Remember, mysql can only use one index per table for most situations. On your users table, the user_xmpp_login_UNIQUE column has been used to join it to the purchase_log table. There fore, the user_registration_timestamp index is not being used on the comparison involving the timestamp column.
One suggestion is to create a composite index on the user_xmpp_login and user_registration_timestamp columns.

Joining 3+ tables using SQL displaying too many results

im trying to create a query to join these tables together using this method below. However it is repeating results and they are not linking up correctly. as in the same rating comment would be on about 4/5 different results etc. its producing 18ish results when im expecting 3. would anyone be willing to help me with this problem?
SELECT a.Company_name,
f.Job_ID,
f.Job_Name,
b.User_Name,
c.Comments,
c.Reliability,
c.Rating
FROM company a,
Users b,
Ratings c,
UserCompJobRating d,
Company_Job e,
Jobs f
WHERE d.Comp_job_ID = e.Comp_Job_ID
AND b.users_ID = d.users_ID
AND c.Rating_ID = d.Rating_ID;
Many Thanks,
Andrew
ok i tried this and it is saying e.Users_ID is an unknown column in 'on clause'
SELECT a.Company_name,
b.Job_ID,
b.Job_Name,
c.User_Name,
d.Comments,
d.Reliability,
d.Rating
FROM Company a, UserCompJobRating e, Jobs b
INNER JOIN Users c
ON c.Users_ID = e.Users_ID
inner join Company_Job f
on e.Comp_Job_ID = f.Comp_Job_ID
inner join Ratings d
on d.Rating_ID = e.Rating_ID;
I'm assuming im close, however way off at the same time?
Ill try to give you some more information:
UserCompJobRating has a primary key UCJR_ID and 3 foreign keys of Comp_Job_ID, Users_ID and Rating_ID
Company_Job table as a primary key Comp_Job_ID, and 2 foreign keys Job_ID, Company_ID
Ratings Table has just the Rating_ID as a primary key and the rest just to do with the rating information
Users Table has a Users_ID as a primary key and basic user information address etc etc
Jobs Table has a Job_ID primary key and basic information about the job, such as name, price, etc.
Company Table has Company_ID as a primary key and the basic company information, similar to the Users table.
Here are the definations:
CREATE TABLE `company` (
`Company_ID` int(11) NOT NULL AUTO_INCREMENT,
`Company_Name` varchar(45) NOT NULL,
`CAddress` varchar(45) NOT NULL,
`CTown` varchar(45) NOT NULL,
`CPostcode` varchar(12) NOT NULL,
`CTelephone` varchar(45) NOT NULL,
PRIMARY KEY (`Company_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
CREATE TABLE `company_job` (
`Comp_Job_ID` int(11) NOT NULL AUTO_INCREMENT,
`Company_ID` int(11) NOT NULL,
`Job_ID` int(11) NOT NULL,
PRIMARY KEY (`Comp_Job_ID`),
KEY `Company_ID_idx` (`Company_ID`),
KEY `Job_ID_idx` (`Job_ID`),
CONSTRAINT `Company_ID` FOREIGN KEY (`Company_ID`) REFERENCES `company` (`Company_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `Job_ID` FOREIGN KEY (`Job_ID`) REFERENCES `jobs` (`Job_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION
CREATE TABLE `jobs` (
`Job_ID` int(11) NOT NULL AUTO_INCREMENT,
`Job_Name` varchar(45) NOT NULL,
`Job_Cost` varchar(45) DEFAULT NULL,
`Job_Avg_Time` varchar(45) DEFAULT NULL,
`Job_Avg_Cost` varchar(45) DEFAULT NULL,
`Job_Description` varchar(45) NOT NULL,
`Company_ID` int(11) NOT NULL,
PRIMARY KEY (`Job_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `ratings` (
`Rating_ID` int(11) NOT NULL AUTO_INCREMENT,
`Comments` varchar(200) DEFAULT NULL,
`Cost` varchar(45) DEFAULT NULL,
`Reliability` varchar(45) DEFAULT NULL,
`Rating` int(11) DEFAULT NULL,
PRIMARY KEY (`Rating_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `usercompjobrating` (
`UCJR_ID` int(11) NOT NULL AUTO_INCREMENT,
`Comp_Job_ID` int(11) DEFAULT NULL,
`Rating_ID` int(11) DEFAULT NULL,
`Users_ID` int(11) DEFAULT NULL,
PRIMARY KEY (`UCJR_ID`),
KEY `Comp_Job_ID_idx` (`Comp_Job_ID`),
KEY `Rating_ID_idx` (`Rating_ID`),
KEY `User_ID_idx` (`Users_ID`),
CONSTRAINT `Comp_Job_ID` FOREIGN KEY (`Comp_Job_ID`) REFERENCES `company_job` (`Comp_Job_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `Rating_ID` FOREIGN KEY (`Rating_ID`) REFERENCES `ratings` (`Rating_ID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `Users_ID` FOREIGN KEY (`Users_ID`) REFERENCES `users` (`Users_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `users` (
`Users_id` int(11) NOT NULL AUTO_INCREMENT,
`User_Name` varchar(45) NOT NULL,
`UAddress` varchar(45) NOT NULL,
`UTown` varchar(45) NOT NULL,
`UPostcode` varchar(45) NOT NULL,
`UTelephone` varchar(45) NOT NULL,
`UDOB` varchar(45) NOT NULL,
PRIMARY KEY (`Users_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
The query needs to look something like this i.e. use this form
SELECT a.Company_name,
f.Job_ID,
f.Job_Name,
b.User_Name,
c.Comments,
c.Reliability,
c.Rating
FROM company a
INNER JOIN Users b
ON a.???? = b.???
Since I dont have your table definitions I cant help you with the JOIN conditions. Show us the tables definition and we would be able to help.
UPDATE:
So based on your table structures you will be looking for something like this:
SELECT *
FROM company cmp
INNER JOIN company_job cmpjb
ON cmp.Company_ID = cmpjb.Company_ID
INNER JOIN jobs jb
ON cmpjb.Job_ID = jb.Job_ID
INNER JOIN usercompjobrating ucmpjbr
ON ucmpjbr.Comp_Job_ID = ucmpjbr.Comp_Job_ID
INNER JOIN users usr
ON usr.Users_id = ucmpjbr.Users_ID
INNER JOIN ratings rat
ON rat.Rating_ID = ucmpjbr.Rating_ID
Note you cannot use the folder table in this join as there are no primary/foreign key relationships to any of the other tables from the folder table.
I would suggest that you carefully dissect this query and let me know if you need to understand the details.
One thing to clarify, what is company_id in table jobs?
select ... (necessary fields to select)
from company c
join company_job cj using (company_id)
join jobs j using (job_id)
join usercompjobrating ucjr using (comp_job_id)
join ratings using (rating_Id)
join users using (users_id)

Nested "select ... in" performance is slow - how to fix?

Here I have a simple join query. If first two queries get results, the whole query can be done in 0.3 secs, but if the first 2 select doesn't fetch any result, the whole query will cost more than half a minute. What causes this difference? How to fix this problem and improve the performance?
SELECT * FROM music WHERE id IN
(
SELECT id FROM music_tag_map WHERE tag_id IN
(
SELECT id FROM tag WHERE content ='xxx'
)
)
LIMIT 10
Here's the table structure:
CREATE TABLE `tag` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index2` (`content`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `music` (
`id` int(7) NOT NULL AUTO_INCREMENT,
`name` varchar(500) NOT NULL,
`othername` varchar(200) DEFAULT NULL,
`player` varchar(3000) DEFAULT NULL,
`genre` varchar(100) DEFAULT NULL,
`sounds` text,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `player` (`player`(255)),
KEY `name` (`othername`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `music_tag_map` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`music_id` int(7) NOT NULL,
`tag_id` int(7) NOT NULL,
`times` int(11) DEFAULT '1',
PRIMARY KEY (`id`),
KEY `music_id` (`music_id`),
KEY `tag_id` (`tag_id`),
CONSTRAINT `music_tag_map_ibfk_1` FOREIGN KEY (`id`) REFERENCES `music` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `music_tag_map_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
There are no joins in that query; there are two sub-selects.
A joined query would be:
SELECT *
FROM music
JOIN music_tag_map ON music.id=music_tag_map.id
JOIN tag ON music_tag_map.tag_id=tag.id
WHERE tag.content = ?
LIMIT 10;
An EXPLAIN applied to each will show you why the join performs better than the sub-select: the sub-select will scan the entire music table (the primary query), while the optimizer can pick the order of tables to scan for the joins, allowing MySQL to use indices to get only the needed rows from all the tables.