selecting only those values from the database which are not selected previously - mysql

I have a table category, profile and employee_belongs_to, where employee_belongs_to stores profile_id and category_id. The profile table stores all the employees details. category table stores different category like English, math,physics ...
I have selected all the employees from profile table which corresponds to particular category. I have all profile ids and category ids in employee_belongs_to table, so i joined the table and selected only those names from profile table whose profile_id corresponds to particular category_is in employee_belongs_to table. The following is the SQL statement i wrote.
SELECT profile.* FROM profile JOIN employee_belongs_to JOIN category ON
employee_belongs_to.Profile_id=profile.Profile_id AND
employee_belongs_to.Category_id=category.Category_id WHERE
category.Category_id=? "
Now i want to select only those employees whose names are not retrieved by above SQL statement. How can i write the SQL statement?

This will allow you to SELECT all columns from table PROFILE, while not including the specific profile ID's:
SELECT p.*
FROM [PROFILE] p
WHERE p.Profile_ID NOT IN (
SELECT p.Profile_ID
FROM [PROFILE] p
INNER JOIN employee_belongs_to ebt ON p.Profile_id = ebt.Profile_id
INNER JOIN category c ON ebt.Category_id = c.Category_id
WHERE c.Category_id = 15);
Also I would recommend using aliases like I've done for readability (p, ebt, c), and changing your INNER JOIN's like I've done.

When you fire above query you will get array of data. And based on that you should store id values from array. And then you can use NOT IN() feature of mysql. Using that you will be able to fetch remain data.
SELECT * FROM tableName
WHERE tableName.id NOT IN (1,2,3);
It will return data which is not consider id's of 1,2 and 3.
I hope it may help you

Related

How to do mysql join to get result form 3 tables

I want to get category id and name from company category table which do not exists in company category cross table. For example the company with id 3 has already category 1 and category 2 and i want the sql result to get category 3
I tried following statement but not getting expected result
SELECT `wp_bmg_company_category`.id, `wp_bmg_company_category`.name
FROM `wp_bmg_company_category`
INNER JOIN `wp_bmg_company_category_cross`
ON `wp_bmg_company_category`.id != `wp_bmg_company_category_cross`.categoryid
if I understood correctly you search category which is now unused.
Select all company data with category ID (return only category ID)
Select all data from category where category id NOT IN (use 1. select data)
And if you find the only unused category for each company separately. Use something like this (ADD company_id for search each company separately, to search unused categories):
SELECT *
FROM category ca
WHERE category_id NOT IN
(SELECT category_id
FROM category c1
JOIN category_cross cc ON c1.id = cc.category_id
WHERE company_id = 1)
What you need is an outer join (left or right) that can retrieve all records from a table, regardless whether it is present in the other table. (You may use not in() or not exists() in place of the outer join).
The other technique you need is called Cartesian join, whereby you match all records from one table with all records from another table. In this case, match all records from the companies table with all records in the categories, to get the complete list of company - category combinations. Then subtract from this the list of categories you have.
select co.id, co.name, ca.id, ca.name
from (wp_bmg_company co join wp_bmg_company_category ca) --this creates the Cartesian join
left join wp_bmg_company_category_cross cr on co.id=cr.companyid and ca.id=cr.categoryid
where cr.id is null --only the non-matched pairs should remain

List of all products with user's saved products

I'm having an issue trying to figure out a query that will allow me to show a list of all of my product as well as showing whether or not a user has saved any given product.
I have 3 tables involved in the query (users, product_user, product).
I am determing whether or not a user has saved a product by joining the three tables and checking if user_id is null or not with the following query:
SELECT products.*, users.id as 'user_id' FROM products
LEFT JOIN product_user ON products.id = product_user.product_id
LEFT JOIN users ON product_user.user_id = users.id AND users.id =1;
However this returns duplicate rows when the user has saved a product (user_id null version and user_id = 1 version). A distinct statement won't work because the rows aren't distinct in this case. What is best practices to ensure that I only get back distinct products? I need to get back the entire list of products, whether or not the user has saved it.
This is being queried in mysql.
I think this does what you want:
select p.*,
(select pu.user_id
from product_user pu
where pu.product_id = p.id and pu.user_id = 1
limit 1
) as user_id
from products p;
This will return only one row per product. The row will have the user_id -- only once and it has to match whatever you pass in.

MySQL: check all values in a subset are in another table and output corresponding IDs

I have 3 tables:
Store(sID, name, address, mID)
Sells(sID, pID)
Product(pID, name, manufacturer, price)
I need to find which stores stock every product from a given manufacturer. For example: to search Unilever, I'd expect to return only stores which stock ALL Unilever products listed in Product, not just some of them.
I've tried lots of different queries with most being completely off the mark.
Am I right in thinking I need to create a subset of all the products made by Unilever, then somehow go through Sells and check that the list of pIDs for each sID contain all of those in the initial subset? I can then join the result with Store to get the store details.
If that's the correct logic, where would one begin?
This creates a subset of all the unilever products:
SELECT pID FROM Product WHERE manufacturer = "Unilever"
How would I then check this list against each store in Sells to find the ones that contain all the products in the list?
One possible way is to join the product table twice, once via the sells table and once directly, then use COUNT(DISTINT ...) on each joined table to check they match
SELECT st.*
FROM store st
INNER JOIN sells se ON st.sID = se.sID
INNER JOIN product pr1 ON se.pID = pr1.pID AND pr1.manufacturer = "Unilever"
INNER JOIN product pr2 ON pr2.manufacturer = "Unilever"
GROUP BY st.sID,
st.name,
st.address,
st.mID
HAVING COUNT(DISTINCT pr1.pID) = COUNT(DISTINCT pr2.pID)
how about creating a Product column in Store table so that all you have to do is search for Unilever Product in the Store table. Then apply this:
SELECT Product FROM Store WHERE Product = "Unilever"
But of course you wouldnt want the column Product in your Store table so my answer cant be correct then

using JOIN and subquery in mysql

I posted a question about 2 weeks ago about 'one to many' relation between SQL tables. Now I have a bit of a different scenario. Basically, there are two tables - coffee_users and coffee_product_registrations. The latter is connected to coffee_users table with 'uid' column. So basically coffee_users.uid = coffee_product_registrations.uid
A single user can have multiple products registered.
What I want to do is to display some product information (from coffee_product_registrations) along with some user information (from coffee_users), BUT retrieve only those rows that have more than 1 product registrations.
So to simplify, here are the steps I need to take:
Join two tables
Select users that have multiple products registered
Display all their products along with their names and stuff
My current SQL query looks like this:
SELECT c.uid, c.name, cpr.model
FROM coffee_users c
JOIN coffee_product_registrations cpr on c.uid = cpr.uid
GROUP BY c.uid
HAVING COUNT(cpr.uid) > 1
This joins the two tables on 'uid' column but displays only 1 row for each user. It selects just users that have multiple products registered.
Now I need to take these IDs and select ALL the products from coffee_product_registrations based on them.
I cannot figure out how to put this in one query.
Replace cpr.*, c.* with columns which you want to extract feom the query
Try this:
SELECT cpr.*, c.*
FROM coffee_product_registrations cpr
INNER JOIN coffee_users c ON c.uid = cpr.uid
INNER JOIN (SELECT cpr.uid
FROM coffee_product_registrations cpr
GROUP BY cpr.uid
HAVING COUNT(DISTINCT cpr.productId) > 1
) AS A ON c.uid = A.uid;

mysql get more than one result from join query

I'm having trouble returning more than one 'tag' from the 'catalog_tag' table when I perform a search query for a specific tag. If I do a search on 'catalog.catalog_id', I do get all the associated tags via the inner joins. Is there a way to grab the tags when searching for a specific tag?
Tables:
catalog table has: catalog_id|name|post_date
catalog_tag_relationship has: catalog_id|tag_id
catalog_tag has: tag_id|tag_name
SQL:
SELECT catalog_id, name, tag.tag_id, tag.tag_name
FROM catalog
INNER JOIN catalog_tag_relationship tagRel ON (tagRel.catalog_id=catalog.catalog_id)
INNER JOIN catalog_tag tag ON (tagRel.catalog_tag_id=tag.tag_id)
WHERE (tag.tag_name='dinosaurs')
Revised:
SELECT
catalog.catalog_id,
catalog.name,
tag.tag_id,
tag.tag_name
FROM (
SELECT
catalog.catalog_id as search_id
FROM catalog
INNER JOIN catalog_tag_relationship tagRel
ON tagRel.catalog_id=catalog.catalog_id
INNER JOIN catalog_tag tag ON tagRel.catalog_tag_id=tag.tag_id
WHERE tag_name='dinosaurs'
GROUP BY catalog.catalog_id
) AS searchList
INNER JOIN catalog ON catalog.catalog_id = search_id
INNER JOIN catalog_tag_relationship tagRel
ON tagRel.catalog_id=catalog.catalog_id
INNER JOIN catalog_tag tag ON tagRel.catalog_tag_id=tag.tag_id
EDIT: This should return the same results as choosing a single list from the catalog table.
Step 1: Find list of catalog ID's matching search criteria.
Step 2: Fill in all catalog information for catalog ID's found in step 1.
This will return multiple rows per catalog entry, but only 1 row per unique catalog <-> tag mapping. If you want one row per catalog you'd need GROUP_CONCAT() to see all the different tags for that catalog.