MySQL LEFT JOIN? - mysql

I have a table cars(id, name) containing 20 rows. The other table carLog(username, car, count) contains rows which count the cars a player has bought (if there is no row if they haven't bought the car)
I want my query to return all twenty cars, and the extra join info, if they've got a row in the carLog table but I can't get it to work.
SELECT * FROM cars LEFT JOIN carLog ON cars.id=carLog.car
This is returning hundreds of rows, I want it to return 20 rows (one for each car), and the extra info in the row if the username has purchased the car:
WHERE carLog.username='Juddling'
I have no idea if I'm meant to be using GROUP BY, WHERE or another type of join!

Move the username condition from the WHERE clause to the ON clause.
SELECT *
FROM cars
LEFT JOIN carLog
ON cars.id=carLog.car
AND carLog.username='Juddling'
The WHERE clause is applied when the JOIN is already completed. This means, it will discard the NULL rows that the LEFT JOIN added.

As you are limiting the table from the outer join, you have to put the condition in the on, not the where:
select * from cars
left join carLog on cars.id = carLog.car and carlog.username = 'Juddling'

Related

SQL count() not showing values of 0

i just started my journey with SQL, and made some tables of Cyclists, and Cycling Teams.
Cyclist's table contains columns: ID, Name, Team (which is foreign key of TEAMS ID)
Team's table contains columns: ID, Name, Number of Cyclists
I want to Count number of Cyclists in each team, by using count() function ( Or basically any function, i just want to make it work )
After many minutes i figured out this query:
SELECT teams.name,
count(*) AS NumberOfCyclists FROM cyclists
JOIN teams ON cyclists.team = teams.id
group by teams.name;
and i Achieved this:
Which is all good, but when i LEFT JOIN i achieve:
My question is: How to get all of the teams (there are 15 of them, not 11), even those where the count of the cyclists is 0?
I think you misunderstand how LEFT JOIN works. The order of tables in the join is important. In a LEFT JOIN, the query returns all the rows in the left table, even if there are no matching rows in the right table. In your query, the left table is cyclists, and the right table is teams.
So your query is currently returning all cyclists, including those who have no team (the result shows that there are 3 cyclists who have no team). This is the reverse of what you want, which is all teams, even those with no cyclists.
If you want to return all the teams, then either reverse the tables in your join:
...
FROM teams
LEFT OUTER JOIN cyclists ON cyclists.team = teams.id
...
Or you could achieve the same result by using RIGHT join.
...
FROM cyclists
RIGHT OUTER JOIN teams ON cyclists.team = teams.id
...
You must count not the amount of rows (COUNT(*)) which cannot be zero but the amount of non-NULL values in definite column (the column which is used in joining condition usage is recommended) taken from right table (COUNT(table.column)). With LEFT JOIN, of course.
But the logic needs teams table to be left. And finally:
SELECT teams.name,
count(cyclists.team) AS NumberOfCyclists
FROM teams
LEFT JOIN cyclists ON cyclists.team = teams.id
group by teams.name;
Try this:
SELECT teams.name,
count(cyclists.id) AS NumberOfCyclists
FROM teams
LEFT JOIN cyclists ON cyclists.team = teams.id
group by teams.name;
The reason why this works instead of the way you have it is because it selects Teams as the base table to draw results from instead of Cyclists.
If there isn't a Cyclist record corresponding to a Team, then the Team is essentially null, and they are grouped together as such (with a null name). By going from Teams into Cyclists, you are saying to take each Team and find the Cyclist records corresponding to the Team, in which case there could be 0 or more.
As you LEFT JOIN, you get all rows from the table cyclists which can have a partner teams, when not all teams rows are NULL
So you have rows that have no oartner

JOIN or Union of two tables - SQL

How can I unite two select statement in one table result?
For instance in the first table I want to get everything however on my 2nd table I only want the corel name that is equal to the corel_id and id of my 2nd table?
SELECT *
FROM garage
UNION
SELECT c.name
FROM corel as c
WHERE EXISTS (SELECT 1 FROM garage as g WHERE c.id = g.corel_id
I tried to execute this but this did not work. Is this right? or is there a better way to do this?
Sorry newbie here.
UPDATE EXPECTED RESULT :
https://anotepad.com/notes/b6662w
Give this a try:
SELECT g.*, c.name
FROM garage g
LEFT JOIN corel c
ON c.id = g.corel_id
Matching two tables in a database is called a join. An inner join, the default, returns only the rows that match from both tables.
A left join returns all the rows from the first table whether or not they match the second, and any data from the second table that matches. The right join does the inverse, returning only non-matching data from the second table. There is also the full join that returns all data regardless of match.
A join statement is what you need. A join puts columns from multiple tables into rows together based in the matching conditions in the where clause.
A union requires 2 or more queries to have the same columns. The union puts the sets of rows together into a longer set or rows.

"MySQL returned an empty result set

I have a table (table1) that I store some people. I need to select random, one by one and add to another table (table2). If a person it's added, that person can be selected one more time until all the people are selected. This is my query:
SELECT * FROM people inner join people_generated on people.id = people_generated.id WHERE people.id != people_generated.id_people ORDER BY RAND() LIMIT 1
The second table "people_generated" is empty so, remain people to generate. Why result is empty?
INNER JOIN returns matching lines from both tables, if one is empty, the result would always be empty.
You probably want to use
SELECT * FROM people LEFT JOIN people_generated on people.id = people_generated.id WHERE people_generated.id_IS NULL ORDER BY RAND() LIMIT 1

MySQL: Return row if joined table contains least one match

(Main table id equal to jid. Join based on that.)
The 1st item has got 2 row in the join table. /That's great./
But 3rd item has got no row in join table.
The question: How can i ignore those items that has got no joined rows? IN ONE QUERY.
I tried the following:
SELECT *
FROM mainTable AS mainT
LEFT JOIN joinTable AS joinT ON mainT.id=joinT.jid
WHERE COUNT(joinT.id) > 0
Replace LEFT JOIN with INNER JOIN, and remove the WHERE clause.

When to use a left outer join?

I don't understand the concept of a left outer join, a right outer join, or indeed why we need to use a join at all! The question I am struggling with and the table I am working from is here: Link
Question 3(b)
Construct a command in SQL to solve the following query, explaining why it had to employ the
(outer) join method. [5 Marks]
“Find the name of each staff member and his/her dependent spouse, if any”
Question 3(c) -
Construct a command in SQL to solve the following query, using (i) the join method, and (ii) the
subquery method. [10 Marks]
“Find the identity name of each staff member who has worked more than 20 hours on the
Computerization Project”
Can anyone please explain this to me simply?
Joins are used to combine two related tables together.
In your example, you can combine the Employee table and the Department table, like so:
SELECT FNAME, LNAME, DNAME
FROM
EMPLOYEE INNER JOIN DEPARTMENT ON EMPLOYEE.DNO=DEPARTMENT.DNUMBER
This would result in a recordset like:
FNAME LNAME DNAME
----- ----- -----
John Smith Research
John Doe Administration
I used an INNER JOIN above. INNER JOINs combine two tables so that only records with matches in both tables are displayed, and they are joined in this case, on the department number (field DNO in Employee, DNUMBER in Department table).
LEFT JOINs allow you to combine two tables when you have records in the first table but might not have records in the second table. For example, let's say you want a list of all the employees, plus any dependents:
SELECT EMPLOYEE.FNAME as employee_first, EMPLOYEE.LNAME as employee_last, DEPENDENT.FNAME as dependent_last, DEPENDENT.LNAME as dependent_last
FROM
EMPLOYEE INNER JOIN DEPENDENT ON EMPLOYEE.SSN=DEPENDENT.ESSN
The problem here is that if an employee doesn't have a dependent, then their record won't show up at all -- because there's no matching record in the DEPENDENT table.
So, you use a left join which keeps all the data on the "left" (i.e. the first table) and pulls in any matching data on the "right" (the second table):
SELECT EMPLOYEE.FNAME as employee_first, EMPLOYEE.LNAME as employee_last, DEPENDENT.FNAME as dependent_first, DEPENDENT.LNAME as dependent_last
FROM
EMPLOYEE LEFT JOIN DEPENDENT ON EMPLOYEE.SSN=DEPENDENT.ESSN
Now we get all of the employee records. If there is no matching dependent(s) for a given employee, the dependent_first and dependent_last fields will be null.
example (not using your example tables :-)
I have a car rental company.
Table car
id: integer primary key autoincrement
licence_plate: varchar
purchase_date: date
Table customer
id: integer primary key autoincrement
name: varchar
Table rental
id: integer primary key autoincrement
car_id: integer
bike_id: integer
customer_id: integer
rental_date: date
Simple right? I have 10 records for cars because I have 10 cars.
I've been running this business for 10 years, so I've got 1000 customers.
And I rent the cars about 20x per year per cars = 10 years x 10 cars x 20 = 2000 rentals.
If I store everything in one big table I've got 10x1000x2000 = 20 million records.
If I store it in 3 tables I've got 10+1000+2000 = 3010 records.
That's 3 orders of magnitude, so that's why I use 3 tables.
But because I use 3 tables (to save space and time) I have to use joins in order to get the data out again
(at least if I want names and licence plates instead of numbers).
Using inner joins
All rentals for customer 345?
SELECT * FROM customer
INNER JOIN rental on (rental.customer_id = customer.id)
INNER JOIN car on (car.id = rental.car_id)
WHERE customer.id = 345.
That's an INNER JOIN, because we only want to know about cars linked to rentals linked to customers that actually happened.
Notice that we also have a bike_id, linking to the bike table, which is pretty similar to the car table but different.
How would we get all bike + car rentals for customer 345.
We can try and do this
SELECT * FROM customer
INNER JOIN rental on (rental.customer_id = customer.id)
INNER JOIN car on (car.id = rental.car_id)
INNER JOIN bike on (bike.id = rental.bike_id)
WHERE customer.id = 345.
But that will give an empty set!!
This is because a rental can either be a bike_rental OR a car_rental, but not both at the same time.
And the non-working inner join query will only give results for all rentals where we rent out both a bike and a car in the same transaction.
We are trying to get and boolean OR relationship using a boolean AND join.
Using outer joins
In order to solve this we need an outer join.
Let's solve it with left join
SELECT * FROM customer
INNER JOIN rental on (rental.customer_id = customer.id) <<-- link always
LEFT JOIN car on (car.id = rental.car_id) <<-- link half of the time
LEFT JOIN bike on (bike.id = rental.bike_id) <<-- link (other) 0.5 of the time.
WHERE customer.id = 345.
Look at it this way. An inner join is an AND and a left join is a OR as in the following pseudocode:
if a=1 AND a=2 then {this is always false, no result}
if a=1 OR a=2 then {this might be true or not}
If you create the tables and run the query you can see the result.
on terminology
A left join is the same as a left outer join.
A join with no extra prefixes is an inner join
There's also a full outer join. In 25 years of programming I've never used that.
Why Left join
Well there's two tables involved. In the example we linked
customer to rental with an inner join, in an inner join both tables must link so there is no difference between the left:customer table and the right:rental table.
The next link was a left join between left:rental and right:car. On the left side all rows must link and the right side they don't have to. This is why it's a left join
You use outer joins when you need all of the results from one of the join tables, whether there is a matching row in the other table or not.
I think Question 3(b) is confusing because its entire premise wrong: you don't have to use an outer join to "solve the query" e.g. consider this (following the style of syntax in the exam paper is probably wise):
SELECT FNAME, LNAME, DEPENDENT_NAME
FROM EMPLOYEE, DEPENDENT
WHERE SSN = ESSN
AND RELATIONSHIP = 'SPOUSE'
UNION
SELECT FNAME, LNAME, NULL
FROM EMPLOYEE
EXCEPT
SELECT FNAME, LNAME, DEPENDENT_NAME
FROM EMPLOYEE, DEPENDENT
WHERE SSN = ESSN
AND RELATIONSHIP = 'SPOUSE'
In general:
JOIN joints two tables together.
Use INNER JOIN when you wanna "look up", like look up detailed information of any specific column.
Use OUTER JOIN when you wanna "demonstrate", like list all the info of the 2 tables.