Inner Joins and Duplicates - mysql

I am trying to join 5 tables together, this brings back multiple duplicates of each row, sometimes the result set will be 150+ rows, which isn't expected, I expect somewhere between 5-7
SELECT DISTINCT
a.user_name, a.date_added, a.guide_title, a.guide_summary, a.before_photo, a.after_photo,
b.product_id,
c.step_number, c.photo, c.photo_caption, c.step_title, c.step_description,
d.tip_text,
e.product_name, e.page_address
FROM customer_stories AS a
INNER JOIN customer_stories_products_used AS b ON a.unique_id = b.story_id
INNER JOIN customer_stories_steps AS c ON a.unique_id = c.story_id
INNER JOIN customer_stories_tips AS d ON a.unique_id = d.story_id
INNER JOIN products AS e ON b.product_id = e.product_id
WHERE a.unique_id = 87
I have also tried GROUP BY, but this just brings back a single row
EDIT:
some info of what the expected results should be:
Each customer_story may have multiple steps (table c), multiple tips(table d) and multiple products used (table b), each of these products used should bring back some information from the products table (e).
each row returned brings back all of the data from (table a) which is always the same, and will also contain data from the other tables multiple times

Related

Return all matched and unmatched values in mysql

I have two table, something like this (simplified):
products with column id and title
outlet data with column id,
product id, and shelf share percentage
I have some data of products in outlet data. I want all the products that are in outlet data with the shelf share percentage and I also want the product that aren't in outlet data. I have implement left outer join but it only returns products that are in outlet data. My query looks like this:
SELECT a.title, b.shelf_share_percentage
FROM cp_product a
LEFT OUTER JOIN cp_outlet_data b
ON a.id = b.product_id
WHERE b.plan_id='9d9184ff-b848-4515-97a2-cea63caddd67'
AND b.visit_id='1586bfd3-8a1b-4f3a-bbc7-eaf61774bb50'
AND b.town_id='414'
AND b.category_id='6'
AND b.shelf_share_id='3'
AND b.outlet_id='0331d624-6fcf-4ac9-8a73-3b60882c5136'
How can I get all the matched and unmatched products?
Just move all the conditions on the cp_outlet_data from the WHERE clause into the ON clause:
SELECT
a.title,
b.shelf_share_percentage
FROM cp_product a
LEFT JOIN cp_outlet_data b
ON a.id = b.product_id AND
b.plan_id = '9d9184ff-b848-4515-97a2-cea63caddd67' AND
b.visit_id = '1586bfd3-8a1b-4f3a-bbc7-eaf61774bb50' AND
b.town_id = 414 AND
b.shelf_share_id = 3 AND
b.outlet_id = '0331d624-6fcf-4ac9-8a73-3b60882c5136'
WHERE
b.category_id = 6;
What is happening in your current query is that, while a left join is initially including all the records from cp_product, even if they do not match, the subsequent WHERE clause is removing certain records. By adding the WHERE logic to the ON clause, all the records will still be retained.

How to select from multiple tables when some of the tables are empty in MySQL

I need to fetch data from 5 tables(all columns of each table) all have FK, which is PK of single table.
But some of the tables may have record may be empty.If data is present on the respective column/table it should return otherwise null/default value
There is one to many and one to one relations on the child tables with parent table.
I have tried so far
- UNION which has concern of same number of columns
- CROSS JOIN not returning any data
- SELECT ALL_COLUMN FROM ALL_TABLE WHERE TABLE.FK=ID Not returning any data
- LEFT JOIN working for 2 tables but not more than that
SELECT A.GENDER, B.BLOCKED_USER FROM t_macroworld_registration AS A
LEFT JOIN t_macroworld_blacklist AS B ON 1=1 WHERE A.ID=15
What are the possible ways I can implement this in a view in MySQL.
Outer join operations are the normative pattern...
SELECT ...
FROM a
LEFT JOIN b ON b.a_id = a.id
LEFT JOIN c ON c.a_id = a.id
LEFT JOIN d ON d.a_id = a.id
WHERE a.id = 15
It's important for the predicates on the outer joined tables to be in the ON clause and not the WHERE clause. If there's any predicate in the WHERE clause requires that a value from one of the outer joined tables be non-NULL, that will negate the "outerness" of the join, making it into an inner join.
The "big rock" problem with this the result when there are more than one matching rows in b, c and d. If there's five rows from b that match, and three rows from c that match, and two rows from b that match, it's going to look like a lot of duplicates. (5x3x2 = 30 rows to be returned, with a lot of duplicated data on those rows.)
Finally I have solved It,
I broke the whole thing into many select query based on FK from each table, so number of additional row returns and mapping has become easy.
Who ever is getting this kind of problem, if it is possible then break it into many select query instead of one.
SELECT
w.id,w.name,a.address,i.name,i.quantity
FROM
warehouse w
LEFT JOIN address AS a ON a.warehouse_id = w.id
LEFT JOIN item AS i ON i.warehouse_id = w.id
LEFT JOIN order AS o ON o.item_id = i.id
WHERE
w.id = 1
GROUP BY 1,2,3,4;
Will give you an overview of your stock and orders for your warehouses. This will also duplicate some results.
Assuming 2 warehouses, 1 address for each, 3 items per warehouse, 2 orders by item = 2 * 3 * 2 = 12 lines
I recommend adding your LEFT JOIN stage by stage and visualizing the result for each stage. You'll quickly understand why lines are multiplying.
Note the usage of foreign keys and ids in the tables to link the tables.
Good luck

Joining multiple MySQL Tables with one relations ID

I have 4 MySQL tables on identity column is in common between all these tables,
Tables in Sequence:
1- Items.
2- Sales.
3- Puchases.
4- Returned.
ItemID appears in all of these tables, WHEN i use LEFT JOIN i get duplicates like:
select
a.ItemID AS ItemID,
a.Item_title AS ItemTitle,
SUM(b.qty) AS SoldQty,
SUM(c.qty) AS PurQty,
SUM(d.qty) AS RetQty
from items a
left join sales b on a.ItemID = b.items_ItemID
left join purchases c on a.ItemID = c.items_itemID
left join returned d on a.ItemID = d.items_ItemID
group by a.ItemID
That query was one of the many tries that i've tried :D the result i get is always unique for sales but duplicates for other tables ..
Thanks for the answer.
If I understand what you're trying to do correctly, you want the total number of sales, purchases, returned etc per item id from a. If that's the case, try thinking about an easier piece of the problem first: how do I get the sum of each sales quantity, grouped by item id?
To do that you'd do something like:
select b.items_ItemID, sum(b.qty) as total_sales_qty
from sales b group by b.items_ItemID
You could do the same thing for tables c and d.
Once you've got those, you can join them all together like this:
select a.ItemID, bb.total_sales_qty, cc.total_purchases_qty, dd.total_returned_qty
from items a
left join (
select b.items_ItemID, sum(b.qty) as total_sales_qty
from sales b group by b.items_ItemID) bb
on a.ItemID = bb.items_ItemID
left join (
select c... etc) cc
on a.ItemID = cc.items_ItemID
... etc
I don't really use MySQL, but in SQL Server, you could use the distinct directive, so duplicate rows appear as just a single row. All the returned columns must be identical, mind you.
Select Distinct a.ItemID AS ItemID,... From....
Hope this helps

How to create the inner query wtih 5 different tables mysql

Having 5 tables
Table a_dates = id,
Table b_types = id, a_date_id, c_type_id,
Table c_types = id, name,
Table d_profiles = id, name, profile_type
Table e_ps = id, a_date_id, d_profile_id
From a_dates Need to get b_types,...then from b_types needs c_types name,... Then compare c_types name with d_profiles name and get d_profiles id.... if equals then create a records in e_ps with a_date_id, d_profile_id.
Could any one please help me in getting the query from inner join.
I tried like, it is incomplete query
INSERT INTO e_ps(id,a_date_id,a_date_type,d_profile_id,c_id)
SELECT '',a.id,'A',dp.id,'67' FROM d_profiles dp
INNER JOIN a_dates a ON {HERE I NEED NAME MATCHING WITH c_types name} = dp.name and dp.profile_type = 'A'
INNER JOIN a_dates ON a.id = a_dates.id
LEFT OUTER JOIN e_ps eps ON eps.a_date_type = 'A' AND eps.a_date_id = a_dates.id
WHERE eps.a_date_id IS NULL
This seems to be a relatively simple JOIN:-
INSERT INTO e_ps(id, a_date_id, d_profile_id)
SELECT NULL, a_dates.id, d_profiles.id
FROM a_dates
INNER JOIN b_types ON a_dates.id = b_types.a_date_id
INNER JOIN c_types ON b.c_type_id = c.id
INNER JOIN d_profiles ON c_types.name = d_profiles.name
With joins there are several types, and I suspect you are getting confused. Briefly:-
With an INNER JOIN it looks for a match that is on BOTH tables. If no
match the no record is returned.
With a LEFT OUTER JOIN it takes a record from the table on the left
and looks for a match on the table on the right. If a match great,
but if not then it still brings a row back but the columns from the
table on the right just have values of NULL.
A RIGHT OUTER JOIN is very much the same, just with the tables
reversed (most people including me avoid using this as it has no
advantages most of the time but just makes things confusing).
With a FULL OUTER JOIN it gets the records from both side, whether
they match or not. If they match then the columns from both are
returned, if not matched then the columns from one are returned. Not
that MySQL does not support a FULL OUTER JOIN (although there are
ways to emulate it).
A CROSS JOIN joins every combination of 2 tables. These are used when
there is no common column to match on but you want all combinations.
For example if you wanted a table of all employees and all days of
the week for each employee you would cross join a table of days of
the week against a table of employees (then for useful data you might
LEFT OUTER JOIN a table of holidays to the result).

How to join mysql query with multiple tables

I have these tables
AssigenmentList --linksto ---School,AgeGroup
Users will have birthday attached to it
AgeGroup in turn linked to many ages like AgeGroup 3-4 is linked to one to many with 3,4 in numerical format
Now i want all the Assignment list which are linked to particular SCHOOL belong to same age as the age of Child
As a general rule:
select a.*, b.*, c.* from
A a inner join B b on a.idB = b.id
inner join C c on b.idC = c.id
You use inner join if a.idB must have match to add the row to the resultset. Left outer join if the mere presence of a.idB (left side) is enough to project the row.
The trick is to navigate from the starting table to the last joining the columns that ties them.