Similar question here but this is slightly different...
I have two tables that I want to join:
location
---------------------------
| id | city | state_id |
---------------------------
| 1 | Denver | 6 |
| 2 | Phoenix | 2 |
| 3 | Seattle | NULL |
---------------------------
state
-------------------
| id | name |
-------------------
| 1 | Alabama |
| 2 | Alaska |
| 3 | Arizona |
| 4 | Arkansas |
| 5 | California |
| 6 | Colorado |
-------------------
SELECT
location.id,
location.city,
state.name
FROM
location
JOIN
state ON state.id = location.state_id;
However, in the case where location.state_id happens to be NULL (perhaps the person inputting the data forgot to select a state), the query would not return a result, but that doesn't mean the location doesn't exist.
How do I get around this problem and somehow display all the locations, even though the state_id might be NULL ?
Use a LEFT OUTER JOIN
SELECT
location.id,
location.city,
state.name
FROM
location
LEFT OUTER JOIN
state ON state.id = location.state_id;
Related
I was trying to learn non-equi joins when I encountered this problem. I have a table pops:
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| country | varchar(100) | YES | | NULL | |
| continent | varchar(100) | YES | | NULL | |
| population | bigint(20) | YES | | NULL | |
I was trying to find countries with their population in the vicinity of say, 100.
select distinct
p1.country,
p2.country,
p1.population,
p2.population
from pops p1
inner join pops p2
on p1.population between p2.population - 100 and p2.population + 100
and p1.country <> p2.country
where p2.country <> p1.country
output I got was:
+------------+------------+------------+------------+
| country | country | population | population |
+------------+------------+------------+------------+
| pakistan | india | 99988 | 99999 |
| china | india | 99990 | 99999 |
| bangladesh | japan | 999 | 999 |
| india | pakistan | 99999 | 99988 |
| china | pakistan | 99990 | 99988 |
| japan | bangladesh | 999 | 999 |
| india | china | 99999 | 99990 |
| pakistan | china | 99988 | 99990 |
+------------+------------+------------+------------+
as we can see, I am getting pairs of (india, pakistan) as well as (pakistan, india), which is data-wise the same thing. Is it possible to eliminate one of the records from the pair?
You could decide to always have the lexographically first (or last, for argument's sake) country on the p1 side - use < (or >) instead of <>.
Also, note that your where clause is redundant, since you already have this condition in the on clause of the join:
select p1.country,
p2.country,
p1.population,
p2.population
from pops p1
inner join pops p2
on p1.population between p2.population - 100 and p2.population + 100 and
p1.country < p2.country
-- Here ------------------^
just change the join condition of p1.country <> p2.country to p1.country < p2.country
I have two tables:
Table students and table of school work delivered
Students table
+--------------------------+---------------------------------+
| id | name |
+--------------------------+---------------------------------+
| 1 | ADAM |
| 2 | BRIGITTE |
| 3 | ANNE |
+--------------------------+---------------------------------+
table student works
+---------------+-------------------------+------------------+
| id_works | works | id_student |
+---------------+-------------------------+------------------+
| 1 | airplane wing | 1 |
| 2 | volcano | 2 |
| 3 | law of gravity | 1 |
| 4 | airplane wing | 3 |
| 5 | law of gravity | 1 |
+-----------------------------------------+------------------+
How do I make a SELECT for work that returns the entire list of students, indicating that the work is delivered? (IMPORTANT: list of all students)
Example
LIST FOR WORK **airplane wing**
+--------------------------+---------------------------------+
| ADAM | X |
| BRIGITTE | |
| ANNE | X |
+--------------------------+--------------------- -----------+
I have tried it with LEF JOIN and IF, but it is not the list of all the students without repeating them.
SELECT
s.name ,
w.work,
w.resid_id,
if(w.work = 'airplane wing', 'X', '') as mark
FROM students s
LEFT JOIN works w
ON s.id = w.id_student
ORDER BY s.name ASC
This will give you a list of all students
And fields id_works and works will be null for those who didn't complete the work
SELECT s.name, w.id_works, w.works
FROM students s
LEFT JOIN works w
ON (w.id_student = s.id AND w.works = 'airplane wing')
ORDER BY s.name ASC
Wasn't sure how to word my question, so sorry if it's a little confusing. Hopefully the below will clear it up a bit.
Here's the query I'm running so far:
select business.name, ifnull(sum(checkin.count),0) as checknum from checkin inner join business on business.id = checkin.business_id where business.state = 'NY' group by business.name order by checknum desc;
and it almost works as intended. There is one more business in NY, which doesn't have any counts in the checkin table, but I can't get it to output.
This is my current output:
+---------------------------------------+----------+
| name | checknum |
+---------------------------------------+----------+
| Lakeside Coffee | 31 |
| McDonalds | 18 |
| Valero | 15 |
| Angelo's Pizza & Grill | 13 |
| Gino's Pizza | 8 |
| Sandy's Deli | 7 |
| Tribeca North Luxury Apartments Homes | 2 |
| Matt & Nat | 2 |
| Filion's Diner | 2 |
| Squirrel's Nest Restaurant and Bar | 2 |
| Best Friends Family Diner | 1 |
| China Buffet | 1 |
| Sandi's Kountry Kitchen | 1 |
| Dick's Country Store | 1 |
+---------------------------------------+----------+
But I need to capture the last business that doesn't have any checkins. Not sure how to tackle this further.
You need to use right join instead of inner join.
Left join will return all rows on the right side of the relationship regardless of whether any key on the left side matches.
I'm new to mySQL, and I'm trying to be able to either SELECT or CREATE A VIEW with the information I want to retrieve from two tables. SQLfiddle
People Table
| people_id | username | Password | Email |
----------------------------------------------
| 1 | username1 | Password1 | Email1 |
| 2 | username2 | Password2 | Email2 |
| 3 | username3 | Password3 | Email3 |
Profile Table
| people_id | id | age | location | hobbies | about |
----------------------------------------------------------------------------------------------------------------------------
| 1 | 1 | 22 | USA | skiing, snowboarding | I am from the US and I like to snowboard |
| 2 | 2 | 45 | Canada | curling, ice skating, reading | I like to ice skate! |
| 3 | 3 | 38 | USA | tv, movies, you name it | I am from the US and I like to watch the tube |
| 2 | 4 | 45 | Canada | curling, reading | I do not like to ice skate anymore |
| 2 | 5 | 46 | Canada | bowling | Bowling is my new favorite hobby! I just turned 46! |
| 1 | 6 | 22 | Brazil | skiing, snowboarding | I am orginally from the US but I just moved to brazil|
I would like to see/retrieve the data like this :
| people_id | username | age | location | hobbies | about |
------------------------------------------------------------------------------------------------------------------------------------
| 3 | username3 | 38 | USA | tv, movies, you name it | I am from the US and I like to watch the tube |
| 2 | username2 | 46 | Canada | bowling | Bowling is my new favorite hobby! I just turned 46! |
| 1 | username1 | 22 | Brazil | skiing, snowboarding | I am orginally from the US but I just moved to brazil|
So I need to select all the people_id and username from table People and then select the people_id row from Profile where the id is the largest number for each people_id
I've tried
SELECT People.people_id, People.username, Profile.age, Profile.location, Profile.hobbies, Profile.about
FROM People
INNER JOIN Profile
ON People.people_id=Profile.people_id
Which gets me closer to what I want, but I don't want to show duplicate rows, I only want to show the last row inserted into the Profile table for each people_id.
SQLfiddle
The most efficient way to get what you want is to use a not exists condition in the where clause. This definitely takes some getting used to. What the query is going to do is to get the matching row from Profile subject to the condition that no other row has a larger id. This is a round-about way of saying "get the biggest id for each person". But, it happens to produce an efficient query plan (and this is true in most databases, not just MySQL).
SELECT p.people_id, p.username, pr.age, pr.location, pr.hobbies, pr.about
FROM People p INNER JOIN
Profile pr
ON p.people_id = pr.people_id
WHERE NOT EXISTS (SELECT 1
FROM Profile pr2
WHERE pr2.people_id = pr.people_id AND
pr2.id > pr.id
);
SELECT People.people_id, People.username, Profile.age, Profile.location, Profile.hobbies, Profile.about
FROM People
INNER JOIN (SELECT * FROM Profile ORDER BY id DESC) AS Profile
ON People.people_id=Profile.people_id
GROUP BY People.people_id
ORDER BY people_id DESC
I have two MySql tables, once for "Locations" and one for "Images". I need to get a list of the most recent Image taken at a particular set of Locations (which is a comma-delimited list), but I only want to return the record for the most recent Image and I've been struggling mightily with getting the right results so far.
So, I have:
Locations:
+---------------------------------------------+
| ID | Name |
|----|----------------------------------------|
| 1 | Indiana |
| 2 | Ohio |
| 3 | Illinois |
+---------------------------------------------+
Images:
+---------------------------------------------+
| ID | User | Location | Date |
|----|-------|-----------|--------------------|
| 1 | Ray | 1 | 2012-06-22 |
| 2 | Robert| 3 | 2011-09-18 |
| 3 | Marie | 1 | 2012-10-01 |
| 4 | Frank | 2 | 2010-12-11 |
| 5 | Debra | 1 | 2008-02-02 |
+---------------------------------------------+
So, right now I have the following:
SELECT Locations.Name, Images.Date, Images.User
FROM Locations INNER JOIN Images ON Locations.ID = Images.Location
WHERE Locations.ID IN ('1','3')
ORDER BY Images.Date DESC
Which returns:
+---------------------------------------------+
| Name | Date | User |
|-------------|-------------|-----------------|
| Indiana | 2012-10-01 | Marie |
| Indiana | 2012-06-22 | Ray |
| Illinois | 2011-09-18 | Robert |
| Indiana | 2008-02-02 | Debra |
+---------------------------------------------+
My question is, how can I get it so that the result returns only the first record with a distinct Location.Name value? So the final, correct result table would look like:
+---------------------------------------------+
| Name | Date | User |
|-------------|-------------|-----------------|
| Indiana | 2012-10-01 | Marie |
| Illinois | 2011-09-18 | Robert |
+---------------------------------------------+
Thanks a lot!
SImply uSe group by::
Select tempTable.Name, tempTable.Date, tempTable.User from
(
SELECT Locations.Name, Images.Date, Images.User, Locations.ID as locationID
FROM Locations
INNER JOIN Images ON Locations.ID = Images.Location
WHERE Locations.ID IN ('1','3')
ORDER BY Images.Date DESC
) as tempTable GROUP BY tempTable.locationID