mysql get more than one result from join query - mysql

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.

Related

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

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

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

Best way to join 3 mySQL tables

I have a tag name and I need to fetch the tag id from the tags table then lookup all the ids that match the tag id in a taxonomy table and then fetch all the items that match the id in the taxonomy table. Can I do it all in 1 query or will I need a subquery? Here is an example of the database structure
tags database
tid, tag
tags taxonomy database
id, wid, tid
items databse
wid, *
I have the tag from the tags database I need to fetch the tid from the tags database then return all the wid's from the taxonomy database where the tid equals what we just fetched and then return * from the items database. I can get this done running 2 separate queries but I'm looking to do it in just 1.
Thanks
You can just JOIN the tables:
select *
from tags tg
left join taxonomy tx
on tg.tid = tx.tid
left join items i
on tx.wid = i.wid
If you are unfamiliar with JOIN syntax here is a good article:
Visual Explanation of JOINs
Try this:
SELECT *
FROM tags t
INNER JOIN taxonomy t2 ON t2.tid = t.tid
INNER JOIN items i ON i.wid = t2.wid
Note that this will return data only for rows that match in all 3 tables.

Checking whole array over a multiple JOIN

To filter a table output of selected entries from a single table i would need something like a multiple JOIN request through several tables.
I want to filter a table of people by a special column in the table. Lets say this column is "tasks." Now tasks is also another table with the column "people" and the values between those two tables are connected with an existant "join" table in the database, which is matching several IDs of one table to each ID of the other table.
Now if this would be simple as that i could just filter with an INNER JOIN and a special condition. The problem is, that the entries of the table "tasks" are connected to another table over a "join" table in the database. To simplify things lets say it is "settings". So each "task" consists of several "settings" which are connected via a join table in their IDs.
So what is the input?
I got an array of IDs, which are representing the settings-ids i do not want to be shown.
What should be the output?
As already said i want a filtered output of "people" while the filter is "settings."
I want the sql request to return each entry of the table "people" with only joined tasks that are not joining any of the "setting-ids" from the array.
I hope you can help me with that.
Thanks in advance!
Example
Settings-Table:
1. Is in progress
2. Is important
3. Has unsolved issues
Tasks-Table: (settings.tasks is the join table between many tasks to many settings)
1. Task from 01.01.2012 - JOINS Settings in 1 and 3 (In progress + unsolved issues)
2. Task from 02.01.2012 - JOINS Settings in 2 (Is important)
3. Task from 03.01.2012 - JOINS Settings in 1 and 2 (...)
People-Table: (people.tasks is the join table between many people to many tasks)
1. Guy - JOINS Tasks in 1, 2, 3 (Has been assigned to all 3 tasks)
2. Dude - JOINS Tasks in 1 (Has been assigned to the Task from 01.01.2012)
3. Girl - JOINS Tasks in 2, 3 (...)
Now there is an array passed to a sql query
[2,3] should return noone because every person is assigned in a task that was either important or had unsolved issues!
[3] would return me only the person "Girl" because it is the only one that is assigned to tasks (2 and 3) that had no unsolved issues.
I hope it is clear now. :)
SELECT DISTINCT PEOPLE.*
FROM PEOPLE INNER JOIN PEOPLE_TASKS ON PEOPLE.PERSON_ID = PEOPLE_TASKS.PERSON_ID
WHERE TASK_ID NOT IN (SELECT DISTINCT TASK_ID
FROM TASK_SETTINGS
WHERE SETTING_ID = <Id you don't want>)
EDIT (for supplying multiple setting ids you don't want)
SELECT DISTINCT PEOPLE.*
FROM PEOPLE INNER JOIN PEOPLE_TASKS ON PEOPLE.PERSON_ID = PEOPLE_TASKS.PERSON_ID
WHERE TASK_ID NOT IN (SELECT DISTINCT TASK_ID
FROM TASK_SETTINGS
WHERE SETTING_ID IN (<Id you don't want>))
First you have to join table people and table tasks with the join table, let's call it people_tasks.
select distinct p.* from people p
inner join people_tasks pt on p.people_id = pt.people_id
inner join tasks on t.tasks_id = pt.tasks_id
Then you have to join table tasks and table settings with the join table, let's call it tasks_settings. You have to join them in the current select.
select distinct p.* from people p
inner join people_tasks pt on p.people_id = pt.people_id
inner join tasks on t.tasks_id = pt.tasks_id
inner join tasks_settings ts on t.tasks_id = ts.tasks_id
inner join settings s on s.settings_id = ts.settings_id
and now you have all people connected with its tasks and its settings. Finally you need the restriction. With the people with the settings selected, you choose the others like this:
select distinct p.people_id from people p
inner join people_tasks pt on p.people_id = pt.people_id
where p.people_id not in (
select distinct p2.people_id from people p2
inner join people_tasks pt2 on p2.people_id = pt2.people_id
inner join tasks t2 on t2.tasks_id = pt2.tasks_id
inner join tasks_settings ts2 on t2.tasks_id = ts2.tasks_id
inner join settings s2 on s2.settings_id = ts2.settings_id
where s2.settings_id in (list of ids)
)

MYSQL - A little bit of trouble/confusion with join query

I am trying to put together a mysql query, that links 3 tables together. In essence, the tables are as follows:
products - Contains product information and basic pricing.
product_depts - Linking table that links products to different departments.
promotions - Another linking table, links promotion periods and prices based on product id.
This is the query:
SELECT p.id, `desc` , price1, price2, cost1, taxable, quantity, deptId, sale
FROM products p
INNER JOIN product_depts ON p.id = prodId
INNER JOIN promotions s ON p.id = s.id
WHERE MATCH (
`desc`
)
AGAINST (
'CLOVER'
IN BOOLEAN
MODE
)
ORDER BY `desc`
LIMIT 0 , 30
If the following line is removed:
INNER JOIN promotions s ON p.id = s.id
And sale taken out of the select clause,
What happens, is ALL the products with a description containing "CLOVER", in the products table, are returned.
With the addition of the removed query parts, only the items that are on promotion (have a matching id in the promotions table), are returned. And any additional products containing "CLOVER" in the products table, that are not "on promotion" are left out.
As I have very limited knowledge with mysql, I thought maybe someone that does have a great deal of knowledge on the matter to share... Would like to provide some input with this.
As i understand it though, this would be essentially the same thing as calling deptId from the product_depts table, which works perfectly. So it is confusing me.
What am i doing wrong that only the items that are "on promotion" are displayed and the additional results are left out?
Thank you!
INNER joins basically say "retrieve all records where there's a matching record in BOTH tables".
If I'm reading your question correctly, it sounds like what you'd want is a LEFT or RIGHT join, which translates to "retrieve all records from one table, and (if any) matching records from the other table.
Sounds like you want to get all products, whether they have a promotion or not, but if they do have a promotion, retrieve the promo info as well.
That'd be
SELECT ...
FROM products
INNER JOIN product_depts ON ...
LEFT JOIN promotions ON ...
So... all products MUST have a department, so do an inner join for that particular part of the query. The left join on promotions makes the 'products' table be the LEFT table, so all records from that table are fetched. The promotions table becomes the RIGHT table, and only provides data for the query results if there's a matching record in the promotions table.
So... given 2 products, 1 of which is on sale, you'd get
product #1 department #1 promoinfo #1
product #2 department #2 NULL
for results. Since there's no matching promo information for the #2 product, you get NULL for the promo data.