Joining 3+ tables using SQL displaying too many results - mysql

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)

Related

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!

SQL - Get total certification count from people on a planet (3 separate tables)

I honestly have no idea how to approach this problem. I've gotten up to SELECT name and then I'm lost (kind of embarrassing).
The problem: 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
Joining them all up doing a count with a group by should do the trick:
SELECT planet.name ,
COUNT(*) AS cert_count
FROM bsg_cert_people people_cert
JOIN bsg_people people ON people.id = people_cert.pid
JOIN bsg_planet planet ON people.homeworld = planet.id
GROUP BY planet.name
SELECT pl.name, count(cert) AS "CertCount"
FROM bsg_planets pl
JOIN bsg_people pe ON pl.id = pe.homeworld
JOIN bsg_cert_people cp ON cp.pid = pe.id
GROUP BY pl.id
I think this is it.

Lookup table in MySQL

I'm doing my first work in PHP/MySQL & I need help. I have one master table:
CREATE TABLE `m4l_movies` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Title` varchar(250) NOT NULL,
`Rating` int(11) NOT NULL,
`Genre` varchar(250) NOT NULL,
`Actors` varchar(250) NOT NULL,
`UserID` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=115 DEFAULT CHARSET=utf8;
that receives input for a form which has values from a these lookup tables:
CREATE TABLE `m4l_actors` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Actor` varchar(255) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=232 DEFAULT CHARSET=utf8;
CREATE TABLE `m4l_genre` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Genre` varchar(255) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=202 DEFAULT CHARSET=utf8;
CREATE TABLE `m4l_movierating` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Movie_Rating` varchar(250) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
& I've created a View:
SELECT m4l_movies.ID AS ID,
m4l_movies.Title AS Title,
m4l_movierating.Movie_Rating AS Rating,
m4l_movies.Actors AS Actors,
m4l_movies.Genre AS Genre
FROM m4l_movies
JOIN m4l_movierating ON m4l_movierating.ID = m4l_movies.Rating
INNER JOIN m4l_genre ON m4l_movies.Genre = m4l_genre.ID
INNER JOIN m4l_actors ON m4l_movies.Actors = m4l_actors.ID
ORDER BY m4l_movies.Title
Here is the out put I get:
----------------------------------------------------------------|
ID Title Rating Actor Genre |
10 Summer G (10,15,25) (45,115,123) |
1 About You G-1 (63,163,405) (3,16,51) |
5 Dog Years P (45,65,95) (98,163,357) |
----------------------------------------------------------------|
Firstly this view should return more than 200 records. Secondly, I need to know how to either create a lookup or some other method to convert the NAME & GENRE back to their corresponding text values. Some how the RATING value is doing it right but I can't get NAME or GENRE to do it correctly. I'm sure it has to do with either the way I've joined the tables but I can't figure out where I'm going wrong. Will someone PLEASE help me.
Ok trying to follow along with suggesting made by Phil I've removed actors, genre from movies tale & created movies_genre & movies_actors
DROP TABLE IF EXISTS `m4l_movies`;
CREATE TABLE `m4l_movies` (
`ID` int(11) NOT NULL auto_increment,
`Title` varchar(250) NOT NULL,
`Year` float NOT NULL,
`Review` varchar(250) NOT NULL,
`Rating` int(11) NOT NULL,
`Image` varchar(250) NOT NULL,
`Storyline` longtext NOT NULL,
`Director` varchar(250) NOT NULL,
`UserID` int(11) NOT NULL default '1',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `m4l_movie_actor` (
movie_id INT(11),
actor_id INT(11),
PRIMARY KEY (movie_id, actor_id),
FOREIGN KEY (movie_id) REFERENCES m4l_movies (ID),
FOREIGN KEY (actor_id) REFERENCES m4l_actors (ID)
);
CREATE TABLE `m4l_movie_genre` (
movie_id INT(11),
genre_id INT(11),
PRIMARY KEY (movie_id, genre_id),
FOREIGN KEY (movie_id) REFERENCES m4l_movies (ID),
FOREIGN KEY (genre_id) REFERENCES m4l_genre (ID)
);
DROP TABLE IF EXISTS m4l_genre;
CREATE TABLE m4l_genre (
ID int(11) NOT NULL auto_increment,
Genre varchar(250) NOT NULL,
PRIMARY KEY (ID)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS m4l_actors;
CREATE TABLE m4l_actors (
ID int(11) NOT NULL auto_increment,
Actor varchar(255) NOT NULL,
PRIMARY KEY (ID)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
but when I try to create the movie_actor OR movie_genre I get
09:29:45
CREATE TABLE `m4l_movie_actor` (movie_id INT(11), actor_id INT(11),
PRIMARY KEY (movie_id, actor_id),
FOREIGN KEY (movie_id) REFERENCES m4l_movies (ID),
FOREIGN KEY (actor_id) REFERENCES m4l_actors (ID) )
Error Code: 1215. Cannot add foreign key constraint
0.000 sec
09:40:56 CREATE TABLE m4l_movie_genre (movie_id INT(11),genre_id INT(11),
PRIMARY KEY (movie_id, genre_id),
FOREIGN KEY (movie_id) REFERENCES m4l_movies (ID),
FOREIGN KEY (genre_id) REFERENCES m4l_genre (ID) )
Error Code: 1215. Cannot add foreign key constraint
0.016 sec
From what I can gather this only occurs when you have data types mismatch, but I THINK I have all INT data types so why am I getting this error?
You appear to have made the classic blunder of storing relational data in an un-relatable way.
You should be using junction tables instead of comma separated values. For example...
CREATE TABLE `m4l_movies` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Title` varchar(250) NOT NULL,
`Rating` int(11) NOT NULL,
-- removed Actors and Genre
`UserID` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`ID`)
);
CREATE TABLE `m4l_movie_actor` (
movie_id INT(11) NOT NULL,
actor_id INT(11) NOT NULL,
PRIMARY KEY (movie_id, actor_id),
FOREIGN KEY (movie_id) REFERENCES m4l_movies (ID),
FOREIGN KEY (actor_id) REFERENCES m4l_actors (ID)
);
-- repeat for genres
You can then join on the junction table and on to the Actors / Genres tables, eg
SELECT ... m4l_actors.Actor ...
FROM m4l_movies
INNER JOIN m4l_movie_actor ON m4l_movies.ID = m4l_movie_actor.movie_id
INNER JOIN m4l_actors ON m4l_movie_actor.actor_id = m4l_actors.ID
If you want the result in a comma separated list, look into GROUP_CONCAT()

Understanding MySql queries

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;

Optimize Join sentence with foreign keys, and show records with nulls

I have the following structure
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
CREATE TABLE IF NOT EXISTS `sis_param_tax` (
`id` int(5) NOT NULL auto_increment,
`description` varchar(50) NOT NULL,
`code` varchar(5) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7;
CREATE TABLE IF NOT EXISTS `sis_param_city` (
`id` int(4) NOT NULL auto_increment,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
CREATE TABLE IF NOT EXISTS `sis_supplier` (
`id` int(15) NOT NULL auto_increment,
`name` varchar(200) NOT NULL,
`address` varchar(200) default NULL,
`phone` varchar(30) NOT NULL,
`fk_city` int(11) default NULL,
`fk_tax` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `fk_city` (`fk_city`),
KEY `fk_tax` (`fk_tax`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
ALTER TABLE `sis_supplier`
ADD CONSTRAINT `sis_supplier_ibfk_4` FOREIGN KEY (`fk_tax`) REFERENCES `sis_param_tax` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
ADD CONSTRAINT `sis_supplier_ibfk_3` FOREIGN KEY (`fk_city`) REFERENCES `sis_param_city` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
My questions are
1. This structure allows me to have a supplier with city and tax fields = null (in case user didn't set these values). Right?
2. If I delete "X" city, supplier's fk_city with city="X" are set to null, same with fk_tax. Right?
3. I want to optimize (IF POSSIBLE) the following join sentence, so I can show suppliers whom have fk_city and/or fk_tax = NULL
SELECT DISTINCT
sis_supplier.id,
sis_supplier.name,
sis_supplier.telefono,
sis_supplier.address,
sis_supplier.phone,
sis_supplier.cuit,
sis_param_city.name AS city,
sis_param_tax.description AS tax,
sis_supplier.fk_city,
sis_supplier.fk_tax
FROM
sis_supplier
LEFT OUTER JOIN sis_param_city
ON
sis_supplier.`fk_city` = sis_param_city.id
LEFT OUTER JOIN `sis_param_tax`
ON
sis_supplier.`fk_tax` = `sis_param_tax`.`id`
Thanks a lot in advance,
Yes.
Yes.
Yes, it's good to optimize. The query you showed looks fine. How is it not working for you?
Have you analyzed the query with EXPLAIN? This can help you tell when you have a query that isn't using indexes effectively. In fact, all of Chapter 7 Optimization would be recommended reading.
if you want to show records with nulls than use RIGHT or LEFT JOIN
depend on your needs