how to query display all data when not all related - mysql

I want to ask ..
If i have data but data related in another table
but i want the output is display all data
usually if data related in another table, I using INNER JOIN but the output just data have a relation, if dont have relation, its not display .. IF I using LEFT JOIN or RIGHT JOIN not all data displayed .. IF I using UNION data duplicated
this just example field .. field in real so many
TABLE A
ID | NAMA |
----------------------
1 | Rina |
2 | Deni |
3 | Muti |
4 | Sina |
5 | Sasa |
TABLE B
ID | Rumah |
----------------------
1 | Jabar |
2 | Jateng |
3 | Jatim |
OUTPUT THAT I WANT
ID | NAMA | Rumah
----------------------------------
1 | Rina | Jabar
2 | Deni | Jateng
3 | Muti | Jatim
4 | Sina | -
5 | Sasa | -

short version:
SELECT COALESCE(a.ID, t2.ID),
COALESCE(a.NAMA, '-')
COALESCE(b.Rumah, '-')
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
RIGHT JOIN TableB t2
ON a.ID = b.ID

If I understand your problem correctly, then a given ID might only have a first or last name, but not both. In this case, simply doing a left or right join will result in the loss of data. One approach here is to do a full outer join between your two tables on the ID, and then use COALESCE to handle possibly missing data appropriately.
SELECT COALESCE(t1.ID, t2.ID) AS ID,
COALESCE(t1.NAMA, '-') AS NAMA,
COALESCE(t2.Rumah, '-') AS Rumah
FROM TableA t1
LEFT JOIN TableB t2
ON t1.ID = t2.ID
UNION
SELECT COALESCE(t1.ID, t2.ID),
COALESCE(t1.NAMA, '-')
COALESCE(t2.Rumah, '-')
FROM TableA t1
RIGHT JOIN TableB t2
ON t1.ID = t2.ID

Related

Display child and parent relationship (if any) in a same table

I have this table
| id |parent|name|
| 1 | NULL | E |
| 2 | NULL | B |
| 3 | 5 | U |
| 4 | 5 | X |
| 5 | NULL | C |
| 6 | NULL | A |
I would like the list, ordered by parent's name, of all ID whether they have a parent or not:
| id |parent|name|has_child|
| 6 | NULL | A | 0 |
| 2 | NULL | B | 0 |
| 5 | NULL | C | 1 |
| 3 | 5 | U | 0 |
| 4 | 5 | X | 0 |
| 1 | NULL | E | 0 |
Is it possible?
I have tried many things but never get the proper answer, and I don't really know how to add the 'has_child' column
SELECT
t1.parent,
t2.name
FROM tablename AS t1
INNER JOIN
(
SELECT MIN(id) AS id, parent
FROM tablename
GROUP BY parent
) AS t22 ON t22.id = t1.id AND t1.parent = t22.parent
INNER JOIN tablename AS t2 ON t1.parent = t2.id;
I would use a self join here:
SELECT DISTINCT
t1.id,
t1.parent,
t1.name,
1 - ISNULL(t2.id) has_child
FROM tablename t1
LEFT JOIN tablename t2
ON t1.id = t2.parent
ORDER BY
t1.id;
The join condition used here, which matches a given record as a parent to one or more children, is that the current id is also the parent of some other record(s). Note that we need SELECT DISTINCT here, because a given parent might match to more than one child record.
You can use a self join -- because you want the name of the parent and not the id -- and coalesce() for ordering:
select t.*,
(case when exists (select 1 from t tc where tc.parent = t.id)
then 1 else 0
end)
from t left join
t tp
on t.parent = tp.id
order by coalesce(tp.name, t.name), -- group rows by the parent, if any
(tp.name is null) desc, -- put parent first
t.name; -- order by children
I hope that you find this answer a little bit useful. The subquery gets the distinct id of parents and excludes the blanked fills.
SELECT *,
CASE WHEN id IN (SELECT DISTINCT parent
FROM tablename
WHERE parent IS NOT NULL)
THEN '1' ELSE '0'
END AS has_child
FROM tablename
ORDER BY name;
SELECT t1.id, t1.parent, t1.name, MAX(t2.parent is not null) has_child
FROM table t1
LEFT JOIN table t2 ON t1.id = t2.parent_id
GROUP BY t1.id, t1.parent, t1.name

MYSQL joining 2 tables accross multiple fields

It should be oh so simple, but perhaps the wine has gone to my head.
Table A (things that need parts)
id | Name | part1 | part2 | part 3 | part 4 | etc
1 | This thing | 1 | 2 | 3 | 2 | etc
2 | another thing | 1 | 1 | 4 | 5 | etc
3 | even more | 11 | 2 | 2 | 2 | etc
Table B (parts)
id | Description
1 | I am a part
2 | I am another Part
3 | Im a very imprtant part
A;; i actually need to do is select all the "parts" that each "thing" needs by its "DESCRIPTION"
so I get a each line in English rather than ID no's
ie
id | Thing name | part 1 | part 2 | part 3 | part 4
1 | This Thing | name of part | name of part | name of part | name of part
Like i said, complete memory overload here and Ive lost the will to live. Any help very gratefull recieved. Thanks in advance.
It will look something like this. Its been a while since I wrote a MySQL query. I am sure somebody could improve on it.
SELECT
a.id,
a.name,
b1.description,
b2.description,
b3.description,
b4.description
FROM
table_a `a`
LEFT JOIN
table_b `b1`
ON a.part1 = b1.id
LEFT JOIN
table_b `b2`
ON a.part2 = b2.id
LEFT JOIN
table_b `b3`
ON a.part3 = b3.id
LEFT JOIN
table_b `b4`
ON a.part4 = b4.id
Your data model has doomed you to complexity from the start.
select
*
from TableA A
left join TableB B1 on A.part1 = B1.id
left join TableB B2 on A.part2 = B1.id
left join TableB B3 on A.part3 = B1.id
left join TableB B4 on A.part4 = B1.id
This is untested, but if you "unpivot" TableA many more possibilities open up.
e.g.
SELECT
A.id
, A.Name
, GROUP_CONCAT(B.Description ORDER BY A.rowno) as PartsList
FROM (
SELECT
A1.id
, A1.Name
, cj.rowno
, CASE
WHEN cj.rowno = 1 THEN part1
WHEN cj.rowno = 2 THEN part2
WHEN cj.rowno = 3 THEN part3
WHEN cj.rowno = 4 THEN part4
END AS LinkID
FROM TableA a1
CROSS JOIN ( 1 AS rowno
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
) cj
) A
LEFT JOIN TableB B ON A.LinkId = B.ID
GROUP BY
A.id
, A.Name
and, if TableA was normalized permanently you would not need these complexities.

joining two tables, select values from two with second table having no records

I have two tables where i fetch values from both tables, the situation is the first table always contains records but second table may or maynot.
here are tables
TAB1
id | rank
1 | TL
2 | PL
3 | MG
TAB2
num | id | swiped_on
1 | 1 | 20-4-14
2 | 1 | 21-4-14
3 | 3 | 25-4-14
the result i want is,(only one record from the second table)
id | rank | swiped_on
1 | TL | 21-4-14
2 | PL | -------
3 | MG | 25-4-14
please help
You can use a left join with a subselect from table tab2
select t.*,t1.swiped_on
from TAB1 t
left join (select id , max(swiped_on) swiped_on
from TAB2 group by id
) t1
on(t.id = t1.id)
Fiddle demo
Or just get the max of swiped_on from tab2
select t.*,max(t1.swiped_on) swiped_on
from TAB1 t
left join TAB2 t1
on(t.id = t1.id)
group by t.id
Fiddle demo

SQL: join table showing null value as well

i have table like this:
table1:
id | item_name | entered_by | modify_by
1 | banana | 2 | 1
2 | apple | 4 | 3
3 | orance | 1 | 1
4 | pineapple | 5 | 3
5 | grape | 6 | 1
table2:
id | username
1 | admin
2 | jack
3 | danny
4 | dummy
5 | john
6 | peter
the query is work fine to select if the entered_by or modify_by do have value:
SELECT t1.id, t1.item_name,
t2enteredBy.username enteredBy,
t2modifyBy.username modifyBy
FROM table1 t1
JOIN table2 t2enteredBy ON t1.entered_by = t2enteredBy.id
JOIN table2 t2modifyBy ON t1.modify_by = t2modifyBy.id
problem: if one of the modifiy_by or entered_by field have null value, the row is now showing out, i need it to show it out as '-' if it has null value rather than hide the row completely.
SQLFIDDLE HERE
Try this out:
SELECT t1.id, t1.item_name,
COALESCE(t2enteredBy.username, '-') enteredBy,
COALESCE(t2modifyBy.username, '-') modifyBy
FROM table1 t1
LEFT JOIN table2 t2enteredBy ON t1.entered_by = t2enteredBy.id
LEFT JOIN table2 t2modifyBy ON t1.modify_by = t2modifyBy.id
Fiddle here.
You need a left join to return those rows with null values. Then the coalesce will make sure that they are replaced by the given string if they are null.
Try this - use LEFT JOIN instead of JOIN
SELECT t1.id, t1.item_name,ifnull(t2enteredBy.username,'-') enteredBy,
ifnull(t2modifyBy.username,'-') modifyBy
FROM table1 t1
LEFT JOIN table2 t2enteredBy ON t1.entered_by = t2enteredBy.id
LEFT JOIN table2 t2modifyBy ON t1.modify_by = t2modifyBy.id
SQL Fiddle Here

mysql select query missing a row

I have a mysql table like this
+---------+----------------+-------+------------+
| dept_id | parent_dept_id | level | name |
+---------+----------------+-------+------------+
| 1 | 0 | 0 | Company |
| 2 | 1 | 1 | HR |
| 3 | 1 | 1 | Finance |
| 4 | 1 | 1 | Operations |
| 5 | 4 | 2 | Sales |
| 6 | 2 | 2 | Training |
+---------+----------------+-------+------------+
I am trying to retrieve all departments and their parent departments. But what I also want is to retrieve the deprtment with ID 1. This guy is the top department and does not have a parent, all I want is a null in the department name.
So far I have this query
select
d1.dept_id,
d2.name as parent_name,
d1.parent_dept_id,
d1.level,
d1.name
from
tdept d1,
tdept d2
where
d1.parent_dept_id = d2.dept_id;
Currently, all departments get retrieved except for the top one, how can I achieve this?
Try using the LEFT OUTER JOIN (The LEFT JOIN keyword returns all rows from the left table (table1), with the matching rows in the right table (table2). The result is NULL in the right side when there is no match.)
select
d1.dept_id,
d2.name as parent_name,
d1.parent_dept_id,
d1.level,
d1.name
from tdept d1
Left outer join tdept d2
where d1.parent_dept_id = d2.dept_id;
Ok, I got it working, I did this:
select
d1.dept_id,
d2.name as parent_name,
d1.parent_dept_id,
d1.level,
d1.name
from
tdept d1 left outer join tdept d2 on d1.parent_dept_id = d2.dept_id;
Thanks Nadeem_MK for putting me in the right direction
Crouz
Try something like this:
select
t1.dept_id,
t2.name,
t1.parent_dept_id,
t1.level,
t1.name
from tdept t1
Left outer join tdept t2
ON t1.parent_dept_id = t2.dept_id;