MySQL, second INNER JOIN - mysql

Hi I trying to do query with couple INNER JOIN, Where is my fault?
SELECT job_tbl.id, accounts.username AS starter, accounts.username AS worker, job_tbl.comment, job_tbl.date, job_tbl.status
FROM job_tbl
INNER JOIN accounts ON job_tbl.starter = accounts.id
INNER JOIN accounts ON job_tbl.worker = accounts.id
job_tbl table here :
+----+---------+--------+---------+------+--------+
| id | starter | worker | comment | date | status |
+----+---------+--------+---------+------+--------+
| 1 | 1 | 3 | qwe | date | 10 |
+----+---------+--------+---------+------+--------+
| 2 | 2 | 1 | qwe | date | 10 |
+----+---------+--------+---------+------+--------+
accounts table here:
+----+------------+-----------+-------+
| id | username | extension | email |
+----+------------+-----------+-------+
| 1 | Julia | 100 | email |
+----+------------+-----------+-------+
| 2 | Eve | 101 | email |
+----+------------+-----------+-------+
| 3 | Max | 102 | email |
+----+------------+-----------+-------+
result I want it to be :
+----+---------+--------+---------+------+--------+
| id | starter | worker | comment | date | status |
+----+---------+--------+---------+------+--------+
| 1 | Julia | Max | qwe | date | 10 |
+----+---------+--------+---------+------+--------+
| 2 | Eve | Julia | qwe | date | 10 |
+----+---------+--------+---------+------+--------+

You're not specifying which accounts table instance to use as starter or worker.
Try this:
SELECT job_tbl.id, job_tbl.description, Starter.username AS starter, Worker.username AS worker, job_tbl.comment, job_tbl.date, job_tbl.status
FROM job_tbl
INNER JOIN accounts AS Starter ON job_tbl.starter = Starter.id
INNER JOIN accounts AS Worker ON job_tbl.worker = Worker.id

The problem is you are joining two table without specifying an ALIAS on table accounts causing ambiguous state.
SELECT a.*,
b.username StarterName,
c.userName WorkerName
FROM job_tbl a
INNER JOIN account b
ON a.starter = b.id
INNER JOIN account c
ON a.worker = c.ID
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins

Related

SQL Query: How to get data from three different tables

I am using mysql and here is the schema that I have.
First Table: Domains
+-----------+--------------------+---------------+
| domain_id | domain_name | campaign_name |
+-----------+--------------------+---------------+
| 1 | test.org | campaign 1 |
| 2 | example.org | campaign 2 |
+-----------+--------------------+---------------+
Second Table: Users
+---------+-----------------+---------------+
| user_id | first_ame | last_name |
+---------+-----------------+---------------+
| 1 | John | Zimmer |
| 2 | Brian | Roberts |
| 3 | Jon | McNeill |
| 4 | Chris | Lambert |
| 5 | Vipul | Patel |
| 6 | Logan | Green |
+---------+-----------------+---------------+
Third Table: Emails
+----------+----------------------------------+-----------+---------+
| email_id | email | domain_id | user_id |
+----------+----------------------------------+-----------+---------+
| 1 | b1#test.org | 1 | 2 |
| 2 | b2#test.org | 1 | 1 |
| 3 | a1#example.org | 2 | 2 |
| 4 | a2#example.org | 2 | 3 |
| 5 | a3#example.org | 2 | 3 |
| 6 | a4#example.org | 2 | 4 |
+----------+----------------------------------+-----------+---------+
I want to get first_name, last_name and email of specific campaign i-e campaign 2 as shown follow.
Here is Online DB Query Editor
Kindly guide me how can I write SQL query to accomplish that. Thanks
If I am not missing anything, this is basically a join. You have the ids nicely matched between the tables, so you can do:
SELECT u.*, e.email, d.campaign_name
FROM Users u JOIN
Emails e
ON u.user_id = e.user_id JOIN
Domains d
ON e.domain_id = d.domain_id
WHERE d.campaign_name = 'campaign 2';
The email table is a so called bridge table between the other two. You have to perform a join between the three tables:
SELECT first_name, last_name, email
FROM Domains JOIN Emails ON Domains.domain_id = Emails.domain_id JOIN Users ON Emails.user_id = Users.user_id
WHERE Domains.campaign_name = ...
SELECT first_name as 'First Name',last_name as 'Last Name', email as 'email ID',campaign_name as 'Compaign Name'
FROM Users u
inner join Emails e
on e.user_id = u.user_id
inner join Domains d
on d.domain_id = e.domain_id

Filter left join output

I have
jobs table with fields
jobId, jobTitle, jobDesc
jobQuotes Table with fields
id, user_id, quote
jobQuotes table has the quote of users who gave quote for the job.
I need those jobs for which a specific user has NOT given any quote.
Using LEFT JOIN I get all the jobs irrespective of the jobQuotes table.
And INNER JOIN only gives all the jobs that has a relevant jobQuote.
But I need those jobs for which a specific user has NOT given any quote.
My Query is
SELECT * FROM dummy_jobs J LEFT JOIN jobQuotes JQ ON J.jobId=JQ.jobId WHERE MATCH (J.jobTitle, J.jobDescription) AGAINST ('php, mysql');
How to filter this result set so that output doesn't have specific user_id in jobQuotes?
SELECT jobstable.jobid from jobstable inner join
(SELECT id from jobQuotes where userid = 953 and quote IS NULL) dummy_table
on dummy_table.id == jobstable.jobid;
The Answer is According to the comment you were given
"I want all jobs for which userId= 953 has not given any quote"
An approach might be to associate a specific user with all jobs by using a cross join and then left join to job quotes with a null test to find those not quoted for.
for example
users
+----+----------+
| id | username |
+----+----------+
| 1 | John |
| 2 | Jane |
| 3 | Ali |
| 6 | Bruce |
| 7 | Martha |
+----+----------+
Jobs
+-------+----------+---------+
| jobId | jobTitle | jobDesc |
+-------+----------+---------+
| 1 | a | a |
| 2 | b | b |
| 3 | c | c |
+-------+----------+---------+
Jobquotes
+------+---------+-------+
| id | user_id | quote |
+------+---------+-------+
| 1 | 3 | 10 |
| 2 | 2 | 10 |
+------+---------+-------+
select t.id,t.username,t.jobid,t.jobtitle,t.jobdesc
from
(
select u.id,u.username, s.jobid,s.jobtitle,s.jobdesc
from users u
cross join (select distinct jobid , jobtitle, jobdesc from jobs) s
where u.id = 3
) t
left join jobquotes jq on jq.id = t.jobid and jq.user_id = t.id
where jq.id is null
result
+----+----------+-------+----------+---------+
| id | username | jobid | jobtitle | jobdesc |
+----+----------+-------+----------+---------+
| 3 | Ali | 2 | b | b |
| 3 | Ali | 3 | c | c |
+----+----------+-------+----------+---------+

MySQL return distinct accounts from one table, average rating from another, all based on service area in another table

as the title states, I'm trying to return a query which gets account details from the accounts table, gets the average rating for the account from the reviews table, and limits the rows to the service location associated to the account.
Here are the simplified tables:
accounts
+----+------------+-----------+
| id | first_name | last_name |
+----+------------+-----------+
| 1 | John | Smith |
| 2 | Bob | Doe |
| 3 | Alice | McLovin |
| 4 | Bruce | Wayne |
+----+------------+-----------+
reviews
+----+-------------+-----+--------+
| id | acccount_id | ... | rating |
+----+-------------+-----+--------+
| 1 | 1 | ... | 9 |
| 2 | 1 | ... | 10 |
| 3 | 2 | ... | 7 |
| 4 | 1 | ... | 2 |
| 5 | 4 | ... | 6 |
+----+-------------+-----+--------+
service_area
+----+-------------+---------+
| id | acccount_id | city_id |
+----+-------------+---------+
| 1 | 1 | 1140 |
| 2 | 1 | 1001 |
| 3 | 2 | 1140 |
| 4 | 1 | 1086 |
| 5 | 4 | 1001 |
+----+-------------+---------+
For example, the user may request to view all accounts which have a service area of city_id 1140. The query should then return the first_name, last_name, and average rating for each account within the specified service area. Note that accounts can have multiple service areas (see service_area table).
Thanks in advance!
UPDATE:
The following QUERY did the trick! I needed a LEFT JOIN for the reviews table!
SELECT a.first_name, a.last_name, AVG(r.rating) avg_rating
FROM accounts a
JOIN service_area sa
ON a.id = sa.account_id AND sa.city_id = 1140
LEFT JOIN reviews r
ON a.id = r.account_id
GROUP BY a.id
You can use joins and simple aggregation with group by
SELECT a.*,
AVG(r.rating) avg_rating
FROM accounts a
JOIN reviews r ON a.id = r.acccount_id
JOIN service_area s ON a.id = s.acccount_id
WHERE s.city_id = 1140
GROUP BY a.id
Result set will be like
id first_name last_name avg_rating
------ ---------- --------- ------------
1 John Smith 7.0000
2 Bob Doe 7.0000
Use LEFT join for when there are no reviews available
SELECT a.*,
COALESCE(AVG(r.rating),0) avg_rating
FROM accounts a
LEFT JOIN reviews r ON a.id = r.acccount_id
JOIN service_area s ON a.id = s.acccount_id
WHERE s.city_id = 1140
GROUP BY a.id
DEMO

Mysql join request

I need to get emtpy fields where data is repeated
For example an customer can have two or more contact persons, so query return (just shorted qyery resul):
CUSTOMER_NAME| CONTACT_PERSON|ETC..
dell | Ighor |etc..
dell | Dima |etc..
but I'm need :
CUSTOMER_NAME| CONTACT_PERSON|etc...
dell | Ighor |etc..
NULL | Dima |etc..
SELECT
`contact`.*,
`branch_has_equipment`.*,
`branch_has_contact`.*,
`equipment`.*,
`customer_has_branch`.*,
`branch`.*,
`customer`.*,
`ip`.*
FROM `customer`
INNER JOIN `customer_has_branch`
ON `customer`.`customer_id` = `customer_has_branch`.`customer_id`
INNER JOIN `branch`
ON `customer_has_branch`.`branch_id` = `branch`.`branch_id`
INNER JOIN `branch_has_equipment`
ON `branch`.`branch_id` = `branch_has_equipment`.`branch_id`
INNER JOIN `equipment`
ON `branch_has_equipment`.`equipment_id` = `equipment`.`equipment_id`
INNER JOIN `branch_has_contact`
ON `branch`.`branch_id` = `branch_has_contact`.`branch_id`
INNER JOIN `contact`
ON `branch_has_contact`.`contact_id` = `contact`.`contact_id`
INNER JOIN `equipment_has_ip`
ON `equipment`.`equipment_id` = `equipment_has_ip`.`equipment_id`
INNER JOIN `ip`
ON `equipment_has_ip`.`equipment_id` = `ip`.`ip_id`
WHERE `customer`.`inservice` = 'Yes'
ORDER BY `customer`.`customer_name`
in additional, tables ^
Customer
customer_id
customer_name
inservice
service_type
comment
Branch
branch_id
city
address
Equipment
equipment_id
brand
model
connection_param
connection_type
serial_number
id
release
Contact
contact_id
name
surname
phone_mobile
phone_work
phone_other
position
customer_has_branch_id
customer_id
branch_id
Since I have no idea how any of those tables relate to one another, my only answer to you is to use an OUTER JOIN, which will keep NULL results.
I'm not seriously advocating this solution because really i think this sort of thing should be handled in application level code (e.g. a bit of PHP), but anyway, consider the following:
SELECT * FROM my_table;
+------+--------+--------+
| game | points | player |
+------+--------+--------+
| 1 | 5 | Adam |
| 1 | 8 | Alan |
| 1 | 7 | Brian |
| 1 | 6 | John |
| 2 | 2 | Adam |
| 2 | 3 | Alan |
| 2 | 4 | Brian |
| 2 | 6 | John |
+------+--------+--------+
SELECT IF(game= #prev,'',game)
, #prev := game
FROM my_table ORDER BY game,player;
+-------------------------+---------------+
| IF(game= #prev,'',game) | #prev := game |
+-------------------------+---------------+
| 1 | 1 |
| | 1 |
| | 1 |
| | 1 |
| 2 | 2 |
| | 2 |
| | 2 |
| | 2 |
+-------------------------+---------------+

Get all users even if no records in another table

I'm facing a problem here :
I have two tables :
A users table :
+----+---------------+----------+
| id | username | company |
+----±---------------±----------+
| 1 | John | 0 |
| 2 | Jack | 0 |
| 3 | Casimir | 0 |
±----±---------------±----------±
A orders table :
+----+---------------+----------+--------+
| id | date | iduser | status |
+----±---------------±----------+--------+
| 1 | 2012-05-28 | 1 | 1 |
| 2 | 2012-05-25 | 1 | 1 |
| 3 | 2012-04-28 | 2 | 1 |
| 4 | 2012-03-28 | 1 | 1 |
| 5 | 2012-02-28 | 2 | 0 |
±----±---------------±----------±--------+
What I'm trying to do is to get a result like this :
+----------+---------------+-------------+
| username | COUNT(order) | MAX(date) |
+----------±---------------±-------------+
| John | 3 | 2012-05-28 |
| Jack | 1 | 2012-04-28 |
| Casimir | 0 | NULL |
±----------±---------------±-------------±
Here's the request I have for the moment :
SELECT u.username, COUNT(o.id), MAX(o.date)
FROM users u
INNER JOIN orders ON u.id = o.iduser
WHERE o.status = 1
GROUP BY u.id
This request gives me a result like :
+----------+---------------+-------------+
| username | COUNT(order) | MAX(date) |
+----------±---------------±-------------+
| John | 3 | 2012-05-28 |
| Jack | 1 | 2012-04-28 |
±----------±---------------±-------------±
As you can see, the user Casimir is not shown as he made no order. How can I modify my request to get the result I need please ?
Thanks !
A LEFT JOIN or LEFT OUTER JOIN will include all rows of the inital table, including those where there is no match in the joined-to table
SELECT u.username, COUNT(o.id), MAX(o.date)
FROM users u
LEFT OUTER JOIN orders o ON u.id = o.iduser AND o.status = 1
GROUP BY u.id
You need to use an OUTER JOIN instead of your current INNER JOIN.
Have a look at Jeff's post here to see how they differ:
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html