MYSQL subquery with a join - mysql

I am trying to retrieve records from 4 tables and want to use a sub query within a left Join. So basically, i have
table a is the table for openings
o,id, o.namesdesc
table b is the table of all the projects
b.id, b.titledesc,b,status,b.edate
table a_b is the table for all the opening that have changed to projects acts like a junction table for one to many
o.id, b.id
table br is the relationship table with other projects
b.id b_rel_code (this is also a b.id as in related to which other projects)
I want to get all the openings,check whether they have project codes from the table a_b table get the projects codes relationship with other project codes check the status of the projects and get all the end_dates of the projects
I would really appreciate your help on this. I have been banging my head from ages. I think i am just not seeing it through
SELECT
o.id,
o.namesdesc,
GROUP_CONCAT(ab.pcode) as junctionpcode,
GROUP_CONCAT(br.scode) as proj_link_code,
GROUP_CONCAT(b.status)
FROM table_ab as ab
Left JOIN tablea as o on ab.oid = o.id
Left Join tableb as b on ab.pcode= b.id
LEFT Join tablebr as br on br.b_rel_code=b.id
where b.status='E'
GROUP BY o.id order by junctionpcode
Many Thanks,
Ok, Probably i have not explained well. May be sample data should help this
Tablea lists description of openings
id,namedesc
1,test desc1
2,test desc2
Tableb list of all the projects
pcode,pname,status,edate
001,test pr1,E,30-10-2017
002,test pr2,E,30-05-2017
003,test pr3,A,30-10-2018
Table br is the relationship table for the projects that are related to other projects
brid pcode rel_pcode
1 001 003
2 003 001
Table a_b which is the junction table between tablea and tableb
abid pcode id
1 001 1
2 002 2
3 003 3
So what i want to achieve is get all the openings(from tablea) that has project codes associated with it(from tablea_b) and get the status and enddates of the projects for only with status E(from table b). But it has needs to consider if that project code has the link to the project code(from table br) which has status and edate.
The output that i am expecting is
a.id,concat(pcode+relcodeany),concat(pstatus,relstatus),concat(pedate,relcodeedate)
1 ,(001,003),(E,A),(30-10-2017,30-10-2018)
I hope i have provided enough info.
Sorry for the long post

What was the problem with the query?
You did not add any sample data or expected result, but couple of notes from the query:
table tablebr is joined through table tableb (br.b_rel_code=b.id), if tableb does not contain any rows for ab.pcode nor you will get any rows from tablebr
The b.status='E' where clause turns the left join for tableb into ordinary join (only rows that match will be included). If you want the left join to be effective move the condition after the ON (on ab.pcode= b.id and b.status='E')
Please provide sample data and expected result.

Related

mysql join query where multiple rows have same key value

I have a table, in a third party database, that has two tables like these:
HISTORY
========
ID | ORDERED
1 PEAS
1 CARROTS
1 SPINACH
2 CARROTS
3 PEAS
3 CARROTS
PEOPLE
=====
ID | NAME
1 Jamal
2 Sharon
3 Mark
I am trying to create a MYSQL query that will return all the PEOPLE who ORDERED both PEAS and CARROTS. The results would be:
Jamal, Mark
When I try this with the OR operator, I get all three people:
SELECT a.ID from people a
INNER JOIN history b on a.ID=b.ID
WHERE b.ordered='PEAS' OR b.ordered='CARROTS'
When I try this with the AND operator, I get no people.
SELECT a.ID from people a
INNER JOIN history b on a.ID=b.ID
WHERE b.ordered='PEAS' AND b.ordered='CARROTS'
How can I write a query to get the names of the people who ordered peas and carrots given the table structure I have to work with?
JOIN twice, once for each condition:
SELECT a.ID
FROM people a
JOIN history b on a.ID=b.ID AND b.ordered='PEAS'
JOIN history c on a.ID=c.ID AND c.ordered='CARROTS'
If history can contain duplicates, or to be defensive, add DISTINCT:
SELECT DISTINCT a.ID
FROM ...
Select all people from people and for each of them the history details, but only the people who ordered PEAS or CARROTS:
When you say "all" people, then you always begin your sql with the people table. When you say "who have", then you add the LEFT JOIN, e.g to the LEFT table (people) you JOIN the wanted details from the right table (history). And when you say "but just the ones having the following details", then you apply a filter, e.g. you use WHERE clause.
SELECT
peo.ID, -- OPTIONAL
peo.NAME,
his.ID, -- OPTIONAL
his.ORDERED
FROM people AS peo
LEFT JOIN history AS his ON his.ID = peo.ID
WHERE
his.ORDERED = "PEAS" OR
his.ORDERED = "CARROTS"
;
Note: "--" means commentar.
EDIT 1:
Important, a principle which you always should apply: Rename the history.ID column to history.PEOPLE_ID and add a new column history.ID as PRIMARY KEY column, in order to uniquely identify each historyrecord.
HISTORY
-------
ID PEOPLE_ID ORDERED
1 1 PEAS
2 1 CARROTS
3 1 SPINACH
4 2 CARROTS
5 3 PEAS
6 3 CARROTS
PEOPLE table remains the same.
EDIT 2:
NO no, it should be an AND in the WHERE clause. My fault. I corrected it.
EDIT 3:
NO no, it should be an OR in the WHERE clause. My fault. I corrected it. AGAIN :-)))

database design best practice connecting multiple tables

sorry if this question has been asked heaps before, but I didn't know how to word it in a way that google would be able to understand.
Basically if for example you have 3 tables:
Table A
Table B1
Table B2
and the data from all 3 tables are connected in 1 of 2 ways either:
Table A & Table B1
OR
Table A & Table B2
Which would be best practice to connect them in a table and why?
1 table such as:
Joined table
|Table A |Table B1 |Table B2 |
|tableA_ID|tableB1_ID|null |
|tableA_ID|null |tableB2_ID|
or have 2 seperate tables for each join
Table A and B1 joined
Table A and B2 joined
Or is there another better way?
Joining table depends upon the Fields and Relationship among the tables.
It also depends on the output you are looking - based on this you will need to join the tables
I think you want a left join, two in fact:
select a.tableA_ID, b1.tableB1_ID, b2.tableB2_ID
from a left join
b1
on a.tableA_ID = b1.tableA_ID left join
b2
on a.tableA_ID = b2.tableA_ID ;
It's a bit unclear what you're trying to do, but given your expected results, union all might work:
select a.tableA_ID,
b.tableB1_ID as TableB1,
null as TableB2
from a join b on a.tableA_ID = b.tableA_ID
union all
select a.tableA_ID,
null,
b2.tableB2_ID
from a join b2 on a.tableA_ID = b2.tableA_ID

SQL search in relations

I have a main table with two relations.
Data structure and example:
A/Employee
id fields
1 Mike Miller
2 Lisa Miller
B/Skill
aid name
1 SQL
1 PHP
C/Language
aid name
1 German
I need a query which shows results from the main table and searches for a keyword in the relation tables.
Search for Miller -> Mike Miller, Lisa Miller
Search for SQL -> Mike Miller
Search for German -> Mike Miller
There are 10.000 rows in the main table and 100.000 relations.
I tried it with JOIN but the query is really slow.
Also the same row from the main table is displayed a view several times when there are more than one relations for this row:
Search for Miller
Returns: Mike Miller, Mike Miller
(Mike Miller displayed more than one time)
SELECT fields
FROM A
JOIN B ON id = B.aid JOIN C ON id = C.aid
WHERE fields LIKE '%"+$search+"%' OR B.name LIKE '%"+$search+"%' OR C.name LIKE '%"+$search+"%'"
I tried to fix the second problem with DISTINCT but now rows without relations are not displayed.
I want to display every row from the main table exactly one time. Which query do I need?
The problem with your first query, as you mention yourself, is that you get several duplicate rows returned. Not strange, since I guess the relation between table A and table B & C is one-to-many.
In your next attempt you added DISTINCT, and that will indeed get rid off the duplicates, but the regular join (or inner join) will only return matches where data can be joined, i.e. where data exists in both joined tables.
Introducing LEFT JOIN:
SELECT DISTINCT fields
FROM A
LEFT JOIN B ON id = B.aid
LEFT JOIN C ON id = C.aid
WHERE fields LIKE '%"+$search+"%' OR B.name LIKE '%"+$search+"%' OR C.name LIKE '%"+$search+"%'"
This will always search all data from table A, and those from table B & C where joins can be made. The DISTINCT will make sure that only unique rows are returned. You could also use GROUP BY for the same result, but that's usually used for aggregate methods.
Use LEFT JOIN.
Example:
SELECT distinct e.empname FROM Employee e
LEFT JOIN skill s ON s.aid = e.id
LEFT JOIN lang l ON l.aid = e.id
WHERE e.empname LIKE '%Miller%' OR s.name LIKE '%Miller%' OR l.name LIKE '%Miller%'
Proof SQL Fiddle

mysql left join duplicates

ive been searching for hours but cant find a solution. its a bit complicated so i'll break it down into a very simple example
i have two tables; people and cars
people:
name_id firstname
1 john
2 tony
3 peter
4 henry
cars:
name_id car_name
1 vw gulf
1 ferrari
2 mustang
4 toyota
as can be seen, they are linked by name_id, and john has 2 cars, tony has 1, peter has 0 and henry has 1.
i simply want to do a single mysql search for who has a (1 or more) car. so the anwser should be john, tony, henry.
the people table is the master table, and im using LEFT JOIN to add the cars. my problem arises from the duplicates. the fact that the table im joining has 2 entries for 1 id in the master.
im playing around with DISTINCT and GROUP BY but i cant seem to get it to work.
any help is much appreciated.
EDIT: adding the query:
$query = "
SELECT profiles.*, invoices.paid, COUNT(*) as num
FROM profiles
LEFT JOIN invoices ON (profiles.id=invoices.profileid)
WHERE (profiles.id LIKE '%$id%')
GROUP BY invoices.profileid
";
try this
select distinct p.name_id, firstname
from people p, cars c
where p.name_id = c.name_id
or use joins
select distinct p.name_id, firstname
from people p
inner join cars c
on p.name_id = c.name_id
If you only want to show people that have a car, then you should use a RIGHT JOIN. This will stop any results from the left table (people) to be returned if they didn't have a match in the cars table.
Group by the persons name to remove duplicates.
SELECT firstname
FROM people P
RIGHT JOIN cars C ON C.name_id = P.name_id
GROUP BY firstname
SELECT DISTINCT firstname
FROM people
JOIN cars ON cars.name_id = people.name_id;
If this doesn't work you might have to show us the full problem.
The way to propose it there's no need for a left join since you need at least a car per person. Left join is implicitely an OUTER join and is intended to return the results with 0 corresponding records in the joinned table.

MySQL create view joining two tables

How can I create a view that merges different columns with a different table? I have three tables for example: users, items and gifts (in this example it's a system that a user can give a gift to another user)
users table has information about users, items table has information about items and gifts table shows which user sent what gift to which user.
What I want is to create a view like following:
user_from | user_to | gift_name | gift_price
sally | john | Teddy Bear | 10
You must join the three tables first. Example
CREATE VIEW GiftsList
AS
SELECT b.name user_from,
c.name user_to,
d.name gift_name,
d.price gift_price
FROM gift a
INNER JOIN users b
ON a.user_from = b.id
INNER JOIN users c
ON a.user_from = c.id
INNER JOIN items d
ON a.item = d.id
You can create a view with two tables like:
CREATE VIEW giftList AS
SELECT users.user_from,users.user_to,gifts.gift_name,gifts.gift_price FROM users,gifts
WHERE users.user_id = gifts.user_id;
The where clause is to make sure the output does not repeat.
I believe were looking for data blending. So basically having google data studio do a JOIN statement on ids from 2 data sets