SELECT p.id, p.first
FROM people p
LEFT JOIN job j ON ( p.job_id = j.id )
LEFT JOIN favourites f ON ( p.company_id = f.company_id )
WHERE p.company_id = 1
I have 3 tables.
Job Favourites People
Each have company_id inside them. When I try the above it outputs p.id,p.first twice. If I remove one of the JOINs then the output is as expected but without the table which was removed.
As I said in the comments what you have here is just an one-to-many relationship which gives you exactly what you are saying.
Like you have a registry on people and you have two favourites to this people on table favourite. To clarify consider the following situation:
Table people:
id name job_id first
1 John 1 1
2 Campos 2 2
Table job
id job
1 Programmer
2 Developer
Table favourites
company_id desc
1 Blah
2 Bleh
1 Blih
On the above model a people have two favourites registries.
For your model it seems that one people can have only one job, but since you did not specify what the table favourites looks like it is probably the the situation i've shown is generating your problem. So to quickly solve it you can use a DISTINCT command like:
SELECT DISTINCT p.id, p.first
FROM people p
LEFT JOIN job j
ON ( p.job_id = j.id )
LEFT JOIN favourites f
ON ( p.company_id = f.company_id )
WHERE p.company_id = 1
Related
The main table has 4 columns:
User Activity Table
userActivityId userId therapistId activityId
1 1 1 1
Each of these columns is a table and these values are all foreign keys.
Basically im trying to run a query that will join to the users table and pull their first and last name based off the user Id.Same thing with therapist - join to the therapist table, pull first + last name.And finally Join to the Activity table and pull the activity name and path from the activity Id
The other tables look like this:
User Table
userId fName lName
Therapist Table
therapistId therapistFirstName therapistLastName
Activity Table
activityId activityTitle activityPath
So far my query looks like
SELECT
User_Activities.userId,
User_Activities.therapistId,
User_Activities.activityId,
Activities.activityTitle,
Activities.activityPath,
Users.fName,
users.lName,
Therapists.therapistFirstName,
Therapists.therapistLastName
FROM
User_Activities
INNER JOIN Users
ON User_Activities.userId = Users.userId
INNER JOIN Therapists ON
User_Activities.therapistId = Therapists.therapistId
INNER JOIN Activities ON
Activities.activityId = User_Activities.userActivityId
WHERE
User_Activities.userId = 1;
When I run this query It only returns 1 row as a result. However there are two activities in the User_Activites table assigned to userId 1.
If I change : INNER JOIN Activities ON
Activities.activityId = User_Activities.userActivityId
from an INNER JOIN to the LEFT JOIN it will display the second row, however the activityTitle and activityPath will be displayed as NULL in the second row.
userActivityId userId therapistId activityId activityId activityTitle activityPath fName lName therapistFirstName therapistLastName
1 1 1 1 1 Brain GZZ0zpUQ S C M D
11 1 1 1 NULL NULL NULL S C M D
You have pretty much answered your question. The second activity does not have a valid ActivityId.
If you want all activities for a user, then you should phrase the query as:
SELECT . . .
FROM Users u LEFT JOIN
User_Activities ua
ON ua.userId = u.userId LEFT JOIN
Therapists t
ON ua.therapistId = t.therapistId LEFT JOIN
Activities a
ON a.activityId = ua.userActivityId
WHERE u.userId = 1;
You want to start with the table where you want to keep all the rows. Then use LEFT JOIN to bring in other tables.
Two other changes of note:
Table aliases are used to simplify reading and writing the query. The SELECT needs to change to use the aliases.
The WHERE clause refers to the Users table rather than UserActivities.
So i have this relational model for hospital (not made by me).
Patient (has an adress and an id), hospital (has id and address), and also there's a table for relationship representing placement in the hospital (hospital.id, patient.id) (also there's other tables, but they don't matter in this query);
The purpose of the query is to find hospitals where is no placed patients from from other cities than hospital's one (on condition that address only contains city).
The problem that i have is theoretical, i don't really know if to use full outer join with a or b null, or something else in the query that finds hospitals containing "foreign" patients, (like join hospital with its placement and then full outer join with a or b table record null, but that leads to a question will i get results in the query? Because i need cities that don't match but all the explanations of that join are about .
Thanks to all who embraced my utterly imperfect english and understood it.
Upd.
Patient:
id=1, city =A;
id=2, city =B;
id=3, city =B;
id=4, city =A;
id=5, city =C;
Hospital:
Id =1, city=A
id =2, city=B;
Placement:
h.id p.id
1 1
1 4
2 2
2 3
2 5
Expected results is "1", id of the first hospital (where's no patients from other city) and others with that "feature"
my query is like
select id from hospital where id not in
(select id,address from hospital inner join placement on h.id=placement.h.id as b inner join patient on placement.p.id=p.id where hospital.address<>patient.address )
Sorry for the delay
Is shawn's query correct?
Can i use h.id instead 1? Idk if our teacher would accept that, because he's never showed us something like that and in 10 years he hasn't managed to create an example of that database for students to test queries on.
select * from hospitals h
where not exists (
select 1 -- dummy value, use h.id if you prefer
from patients p inner join placement pl on pl.pid = p.id
where pl.hid = h.id and p.city <> h.city
)
or
select h.id
from hospitals h
left outer join
placement pl inner join patients p on p.id = pl.pid
on pl.hid = h.id
group by h.id
-- this won't count nulls resulting from zero placements for that hospital
-- as long as standard sql null comparisons are active
having count(case when h.city <> p.city then 1 end) = 0
Looks like it works to me: http://rextester.com/BTJB59061
I have a table called reviews. I get the most current user reviews like this:
SELECT b.item, b.item_id, a.review_id, a.review, c.category, u.username, c.cat_id
FROM reviews a
INNER JOIN items b
ON a.item_id = b.item_id
INNER JOIN master_cat c
ON c.cat_id = b.cat_id
INNER JOIN users AS u
ON u.user_id = a.user_id
ORDER BY a.review_id DESC;
What I want to do is slightly alter it to be more personable for users.
I have another table of user "connections". Kind of like Twitter. When a user follows someone, it gets logged in this table called profile_follow. This has three columns. id, user_id, follow_id. Simply: If I am user #1, and I "follow" user # 3 and user #5, two rows will be added in this table:
profile_follow
------------------------
id | user_id | follow_id
| 1 | 3
| 1 | 5
Here is how I want to change the query above. I want to only show newest reviews, from people you follow.
So I will need at least one more join, for table profile_follow. And I need to pass in a user_id (it's a php function), doing something like `WHERE profile_follow.user_id = '{$user_id}'. I think I will have to add a sub query on this, not use.
Can someone show me how to finish this query? I am not sure how to handle it from here? All of my attempts have been off so far.
I think I need to do something like:
Selectfollow_idwhereuser_id= (logged in user)
And then in the main query:
Select reviews only with profile_follow.follow_id = review.user_id.
I can't figure out how to make this filter work.
Always difficult without testing, but:
SELECT b.item, b.item_id, a.review_id, a.review, c.category, u.username, c.cat_id
FROM reviews a
INNER JOIN items b
ON a.item_id = b.item_id
INNER JOIN master_cat c
ON c.cat_id = b.cat_id
INNER JOIN profile_follow pf
ON pf.follow_id = a.user_id
WHERE profile_follow.user_id = '{$user_id}'
ORDER BY a.review_id DESC;
I have three tables persons, jobs, jobs_persons
One person can have multiple jobs.
Person 1 is Technical Support AND Manager
Person 2 is Technical Support
Person 3 Is Manager
Job 1 Technical Support
Job 2 Manager
I need to find a query give me the result for the person who currently is Technical Support AND Manager
The answer would be only Person 1
SELECT persons.*
FROM persons INNER JOIN jobs_persons ON persons.id = jobs_persons.person_id
INNER JOIN jobs ON jobs.id = jobs_persons.job_id
WHERE job.id IN (1,2)
Returns 3 rows
SELECT persons.*
FROM persons INNER JOIN jobs_persons ON persons.id = jobs_persons.person_id
INNER JOIN jobs ON jobs.id = jobs_persons.job_id
WHERE job.id = 1 AND job.id = 2
Returns 0 rows.
I'm currently working on Ruby on Rails.
Somebody can help?
You want to use an OR operator. Using job.id = 1 AND job.id = 2 will only return elements where id equals 1 and at the same time 2. No element can do that. You want elemets where th id is 1 or where the id is 2.
to make it more obvious:
SELECT * FROM table WHERE lastname = 'Smith' AND firstname = 'James';
when executing this you obviously don't want everybody who is called Smith or James. ;-)
EDIT:
Misread the question. what you need is a second join to join the jobs table two times in and join them with the different jobs. It is a bit hard as you didn't show the schema, but this might work:
SELECT persons.*
FROM persons
INNER JOIN jobs_persons jp1 ON persons.id = jp1.person_id
INNER JOIN jobs_persons jp2 ON persons.id = jp2.person_id
INNER JOIN jobs j1 ON j1.id = jp1.job_id
INNER JOIN jobs j2 ON j2.id = jp2.job_id
WHERE j1.id = 1 AND j2.id = 2
Try this to get all the person who has got a job of 1 AND 2 in your associative entity table. No need to hit the job table.
SELECT p.*
FROM persons p
WHERE id in (
SELECT person_id FROM jobs_persons
WHERE job_id IN (1,2)
GROUP BY person_id
HAVING COUNT(*) = 2
);
With your recent comments, it seems you're having performance problems. That's really outside of the scope of this question and answer.
You need to make sure your indexes are in place on the appropriate columns:
jobs_person.job_id
persons.id
I'm working on a mysql query in a Drupal database that pulls together users and two different cck content types. I know people ask for help with groupwise maximum queries all the time... I've done my best but I need help.
This is what I have so far:
# the artists
SELECT
users.uid,
users.name AS username,
n1.title AS artist_name
FROM users
LEFT JOIN users_roles ur
ON users.uid=ur.uid
INNER JOIN role r
ON ur.rid=r.rid
AND r.name='artist'
LEFT JOIN node n1
ON n1.uid = users.uid
AND n1.type = 'submission'
WHERE users.status = 1
ORDER BY users.name;
This gives me data that looks like:
uid username artist_name
1 foo Joe the Plumber
2 bar Jane Doe
3 baz The Tooth Fairy
Also, I've got this query:
# artwork
SELECT
n.nid,
n.uid,
a.field_order_value
FROM node n
LEFT JOIN content_type_artwork a
ON n.nid = a.nid
WHERE n.type = 'artwork'
ORDER BY n.uid, a.field_order_value;
Which gives me data like this:
nid uid field_order_value
1 1 1
2 1 3
3 1 2
4 2 NULL
5 3 1
6 3 1
Additional relevant info:
nid is the primary key for an Artwork
every Artist has one or more Artworks
valid data for field_order_value is NULL, 1, 2, 3, or 4
field_order_value is not necessarily unique per Artist - an Artist could have 4 Artworks all with field_order_value = 1.
What I want is the row with the minimum field_order_value from my second query joined with the artist information from the first query. In cases where the field_order_value is not valuable information (either because the Artist has used duplicate values among their Artworks or left that field NULL), I would like the row with the minimum nid from the second query.
The Solution
Using divide and conquer as a strategy and mysql views as a technique, and referencing this article about groupwise maximum queries, I solved my problem.
Create the View
# artists and artworks all in one table
CREATE VIEW artists_artwork AS
SELECT
users.uid,
users.name AS artist,
COALESCE(n1.title, 'Not Yet Entered') AS artist_name,
n2.nid,
a.field_image_fid,
COALESCE(a.field_order_value, 1) AS field_order_value
FROM users
LEFT JOIN users_roles ur
ON users.uid=ur.uid
INNER JOIN role r
ON ur.rid=r.rid
AND r.name='artist'
LEFT JOIN node n1
ON n1.uid = users.uid
AND n1.type = 'submission'
LEFT JOIN node n2
ON n2.uid = users.uid
AND n2.type = 'artwork'
LEFT JOIN content_type_artwork a ON n2.nid = a.nid
WHERE users.status = 1;
Query the View
SELECT
a2.uid,
a2.artist,
a2.artist_name,
a2.nid,
a2.field_image_fid,
a2.field_order_value
FROM (
SELECT
uid,
MIN(field_order_value) AS field_order_value
FROM artists_artwork
GROUP BY uid
) a1
JOIN artists_artwork a2
ON a2.nid = (
SELECT
nid
FROM artists_artwork a
WHERE a.uid = a1.uid
AND a.field_order_value = a1.field_order_value
ORDER BY
uid ASC, field_order_value ASC, nid ASC
LIMIT 1
)
ORDER BY artist;
A simple solution to this can be to create views in your database that can then be joined together. This is especially useful if you often want to see the intermediate data in the same way in some other place. While it is possible to mash together the one huge query, I just take the divide and conquer approach sometimes.