Join results from two selects - mysql - mysql

I have two select queries:
SELECT Name as CategoryName FROM providerscategories where ID in(
Select catId from provider_in_category
where providerUsername = 'a' group by providerUsername
);
and the other one is:
SELECT Username, providerName from serviceproviders where Username in(
SELECT providerUsername from usedproviders where Username='Admin')
Basically what it does is getting the providerName from the usedProviders by Username from usedproviders table, then gets the UserName and the providerName of the provider based on the results.
Then I want to check which category this provider is in and get this category name, and add it to the UserName and the providerName of the category.
Here is a sql fiddle link: SQL Fiddle
the desired result set is:
Username | ProviderName | categoryName

OK. Let's start here... what part of the problem does the following query not solve...
SELECT sp.*
, up.username
, c.name
, pc.catid
FROM usedproviders up
JOIN serviceproviders sp
ON sp.username = up.providerusername
JOIN provider_in_category pc
ON pc.providerusername = up.providerusername
JOIN providerscategories c
ON c.id = pc.catid
WHERE up.username = 'Admin';
+----------+--------------+----------+--------------+-------+
| Username | providerName | username | name | catid |
+----------+--------------+----------+--------------+-------+
| a | providerA | Admin | CategoryName | 1 |
| b | providerB | Admin | CategoryName | 1 |
+----------+--------------+----------+--------------+-------+

This is what you can do
select
sp.Username,
sp.providerName,
Name
from serviceproviders sp
left join
(
select
usedproviders.ProviderUsername ,
providerscategories.Name
from
provider_in_category pic
inner join
usedproviders on usedproviders.ProviderUsername = pic.providerUsername
inner join
providerscategories on providerscategories.ID = pic.catId
where
usedproviders.ProviderUsername = 'a'
AND usedproviders.Username = 'admin'
group by usedproviders.ProviderUsername
)t
on sp.Username = t.ProviderUsername
DEMO
I have seen you are filtering data with admin and a so if you dont want to see the 2nd record NULL then instead LEFTJOIN just make it INNER join the first part.
Also if you do not want filter then remove the where clause and will list all data.
something as DEMO

Related

Mysql join table and select when record doesn't exit in left join

I have a table which list available items, when user click on any item it will insert in added_items table. Now my problem is I want to use join to select all items that any user has not added. My current query doesn't show items if one user has added it.
items
name | type | id | user
-------|------|----|------------------
JAVA | A | 1 | SYSTEM
PHP | A | 2 | SYSTEM
HTML | B | 3 | USER1
added_items
item_id | user
----------|--------------
1 | peter
My query
SELECT it.*
FROM items it
LEFT JOIN added_items ait
ON ait.user = it.user
#on ait.item_id = it.id
WHERE it.type = "A"
AND ait.user IS NULL
The second query I tried
SELECT it.*
FROM items it
LEFT JOIN added_items ait
ON ait.item_id = it.id
WHERE it.type = "a"
AND ait.user != "peter"
Expected result
when current user is peter I want to retrieve only PHP as peter has added JAVA.
But if current user isn't on added_items the retrieve all record.
Add fiddle http://sqlfiddle.com/#!9/3761e40
SELECT *
FROM items
WHERE NOT EXISTS ( SELECT NULL
FROM added_items
WHERE items.id = added_items.item_id
-- AND added_items.user = "peter"
)
-- AND items.type = 'A'
fiddle
You can try:
SELECT it.*
FROM items it
LEFT JOIN added_items ait
ON ait.item_id = it.id
WHERE ait.item_id IS NULL

How can this be done in a single select statement?

I've got these three tables in the DB & I want to select the event_name for a specific userID from t1event given that I know the value of ID from t1user. How can I do this in a single select statement. (I am using mysql).
**t1user**
+----+
| ID |
+----+
**t2userEvent**
+---------+----------+
| userID | eventID |
+---------+----------+
**t1event**
+----------+--------------+
| eventID | event_name |
+----------+--------------+
Use join:
SELECT t1user.ID, t1event.event_name
FROM t1user
JOIN t2userEvent ON t1user.ID = t2userEvent.userID
JOIN t1event ON t1event.eventID = t2userEvent.eventID
WHERE t1user.ID = :user_id
If you want the users who doesn't have events be listed too, then use LEFT JOIN instead.
You could try this:
SELECT A.event_name FROM t1event A INNER JOIN t2userEvent B
ON A.eventID = B.eventID WHERE b.userID = ?
If I understand it correctly you have the userID as parameter?

MySQL JOIN+COUNT+WHERE+AND

I have table of regions:
table region:
id | title
Region has many adverts:
table advert:
id | region_id | ...
Then advert has many uses (many-many through table adv_use):
table use:
use | slug | ...
----------------
1 | slug_1 | ...
2 | slug_2 | ...
..................
table adv_use:
adv_id | use_id
I want select all regions with count(*) of adverts, which have uses with slug_1 AND slug_2. If advert has no use with slug_1 or with slug_2 (or both), it's must not be counted.
What i have now:
SELECT COUNT(DISTINCT advert.id) as count
FROM region
JOIN advert ON region.id = advert.region_id
JOIN adv_use ON advert.id = adv_use.adv_id
JOIN use ON adv_use.use_id = use.id
WHERE use.slug IN ('slug_1', 'slug_2')
GROUP BY region.id
HAVING COUNT(DISTINCT adv_use.use_id) = 2
But it's working not as i want.
SQLFiddle: http://sqlfiddle.com/#!2/5b4d4/1
Thanks for help and sorry for bad english.
You need to use a subquery to select the adv_id that use both slugs:
SELECT COUNT(DISTINCT advert.id) as count, region.id as reg_id
FROM region
JOIN advert ON region.id = advert.region_id
JOIN (SELECT adv_use.adv_id
FROM adv_use
JOIN tbl_use ON adv_use.use_id = tbl_use.id
WHERE tbl_use.slug IN ('slug1', 'slug2')
GROUP BY adv_use.adv_id
HAVING COUNT(DISTINCT adv_use.use_id) = 2) adv_use
ON advert.id = adv_use.adv_id
GROUP BY region.id
;
SQLFIDDLE

How would I execute this complex conditional multi-table MySQL join (queries provided)?

Ok I have a few tables tables. I am only showing relevant fields:
items:
----------------------------------------------------------------
name | owner_id | location_id | cab_id | description |
----------------------------------------------------------------
itm_A | 11 | 23 | 100 | Blah |
----------------------------------------------------------------
.
.
.
users:
-------------------------
id | name |
-------------------------
11 | John |
-------------------------
.
.
.
locations
-------------------------
id | name |
-------------------------
23 | Seattle |
-------------------------
.
.
.
cabs
id | location_id | name
-----------------------------------
100 | 23 | Cool |
-----------------------------------
101 | 24 | Cool |
-----------------------------------
102 | 24 |thecab |
-----------------------------------
I am trying to SELECT all items (and their owner info) that are from Seattle OR Denver, but if they are in Seattle they can only be in the cab NAMED Cool and if they are in Denver they can only be in the cab named 'thecab' (not Denver AND cool).
This query doesn't work but I hope it explains what I am trying to accomplish:
SELECT DISTINCT
`item`.`name`,
`item`.`owner_id`,
`item`.`description`,
`user`.`name`,
IF(`loc`.`name` = 'Seattle' AND `cab`.`name` = 'Cool',1,0) AS `cab_test_1`,
IF(`loc`.`name` = 'Denver' AND `cab`.`name` = 'thecab',1,0) AS `cab_test_2`,
FROM `items` AS `item`
LEFT JOIN `users` AS `user` ON `item`.`owner_id` = `user`.`id`
LEFT JOIN `locations` AS `loc` ON `item`.`location_id` = `loc`.`location_id`
LEFT JOIN `cabs` AS `cab` ON `item`.`cab_id` = `cabs`.`id`
WHERE (`loc`.`name` IN ("Seattle","Denver")) AND `cab_test_1` = 1 AND `cab_test_2` = 1
I'd rather get rid of the IFs is possible. It seems inefficent, looks clunky, and is not scalable if I have a lot of location\name pairs
Try this:
SELECT DISTINCT
item.name,
item.owner_id,
item.description,
user.name
FROM items AS item
LEFT JOIN users AS user ON item.owner_id = user.id
LEFT JOIN locations AS loc ON item.location_id = loc.id
LEFT JOIN cabs AS cab ON item.cab_id = cabs.id
WHERE ((loc.name = 'Seattle' AND cab.name = 'Cool')
OR (loc.name = 'Denver' AND cab.name = 'thecab'))
My first thought is to store the pairs of locations and cab names in a separate table. Well not quite a table, but a derived table generated by a subquery.
You still have the problem of pivoting the test results into separate columns. The code can be simplified by making use of mysql boolean expressions, which get rid of the need for a case or if.
So, the approach is to use the same joins you have (although left join is not needed because the comparison on cab.name turns them in to inner joins). Then add a table of the pairs you are looking for, along with the "test name" for the pair. The final step is an explicit group by and a check whether conditions are met for each test:
SELECT i.`name`, i.`owner_id`, i.`description`, u.`name`,
max(pairs.test_name = 'test_1') as cab_test_1,
max(pairs.test_name = 'test_2') as cab_test_2
FROM `items` i LEFT JOIN
`users` u
ON i.`owner_id` = u.`id` LEFT JOIN
`locations` l`
ON i.`location_id` = l.`location_id` left join
`cabs` c
ON i.`cab_id` = c.`id` join
(select 'test_1' as testname, 'Seattle' as loc, 'cool' as cabname union all
select 'test_2', 'Denver', 'thecab'
) pairs
on l.name = pairs.name and
l.cabname = c.name
group by i.`name`, i.`owner_id`, i.`description`, u.`name`;
To add in additional pairs, add them into the pairs table along, and add an appropriate line in the select for the test flag.

retrieving data from three tables using MySQL

i am having three tables namely
1)cd_register
|----------------------------------------------------|
| username | name | age | sex | dob |
|----------------------------------------------------|
2)cd_social
|-------------------------------------|
| username | religion | caste |
|-------------------------------------|
and
3)cd_professional
|----------------------------------------|
| username | occupation | education |
|----------------------------------------|
now i'm using this query in mysql but its giving error
SELECT cd_register.name, cd_register.age, cd_register.dob, cd_social.religion, cd_social.caste, cd_professional.profession
FROM cd_register, cd_social,cd_professional
WHERE
cd_register.sex = 'Male',
cd_social.religion = 'Hindu',
cd_social.caste = 'Brahmin',
cd_professional.occupation = 'Doctor',
cd_register.username = cd_social.username AND
cd_register.username = cd_professional.username
now i want to mention that username is the primary key of all the tables. Also
username of cd_register is foreign key in cd_social. Also
username of cd_register is foreign key in cd_professional.
You can use join
SELECT t1.name, t1.age, t1.dob, t2.religion, t2.caste, t3.profession
FROM cd_register as t1
LEFT JOIN cd_social as t2
ON t1.username = t2.username and t2.caste = 'Brahmin' and t2.religion ='Hindu'
LEFT JOIN cd_professional as t3
ON t1.username = t3.username and t3.occupation = 'Doctor'
WHERE t1.sex = 'Male'
You have commas in your WHERE clause, which will definitely cause an error (you probably want ANDs there) Try this:
SELECT cdr.name, cdr.age, cdr.dob, cds.religion, cds.caste, cdp.profession
FROM cd_register cdr
JOIN cd_social cds
ON cdr.username = cds.username
JOIN cd_professional cdp
ON cdr.username = cdp.username
WHERE cdr.sex = 'Male'
AND cds.religion = 'Hindu'
AND cds.caste = 'Brahmin'
AND cdp.occupation = 'Doctor'
It might help to tell us what the error is.
Also, the last two lines are identical.
You probably need to join the cd_professional table, too.