One select on two tables with NULL and not null - sql

I try to get select from two tables and put some data from one to other with ussing WHERE
(PL/SQL)
I have two tables like those:
table1
ID NAME COLOR COMPANY_SHORT_NR
1 a Green 1
2 b Red 23
3 c Blue null
4 a Green null
5 g Green 1
table2
ID SHORT COMP_NAME
1 1 company_name_1
2 23 comapny_name_2
and now I would like to get all data from table 1 with companies names and if its null get info it is null like that
1 a Green company_name_1
2 b Red comapny_name_2
3 c Blue null
4 a Green null
5 g Green company_name_1
I tried do it like this:
select ID
,NAME
,COLOR
,COMPANY_SHORT_NR
from table1
,table2
where COMPANY_SHORT_NR = SHORT
but this give me only not null values:
1 a Green company_name_1
2 b Red comapny_name_2
5 g Green company_name_1
if i use sth like this:
select ID
,NAME
,COLOR
,COMPANY_SHORT_NR
from table1
,table2
where COMPANY_SHORT_NR = SHORT or COMPANY_SHORT_NR is null
I get thousends of records ...
If I use only IS NULL than it returns me only 2 rows as it should be.
Where I make mistake ?

You have to use left join as below
select ID
,NAME
,COLOR
,COMPANY_SHORT_NR
from table1 t1
left join table2 T2 on t1.COMPANY_SHORT_NR = t2.SHORT

you neen OUTER JOIN for that
select ID
,NAME
,COLOR
,COMPANY_SHORT_NR
from table1
LEFT OUTER JOIN table2 ON ( COMPANY_SHORT_NR = SHORT )

wouldn't it be better to join the tables? like SELECT ID, NAME, COLOR, COMPANY_SHORT_NR FROM table1 t1 LEFT JOIN table2 t2 on t2.SHORT = t1.COMPANY_SHORT_NR WHERE 1

Related

SQL - Delete specific set of raw in a table using another table

Tabel 1 :
ID1
ID2
ID3
MainID
Location
1
A
X
1AX
VIC
2
B
Y
2BY
SYD
3
C
W
3CW
TAS
4
D
Z
4DZ
TAS
Tabel 2 :
SALESID
QTY
AMT
DIFF
1AX
1
100
2
2BY
2
0
3
3CW
3
5
4DZ
3
12
2
Ignore other fields, I need to delete all raws in Tabel 1 where AMT in Tabel 2 has zero or no value for the SALESID.
For example, after the query, only raws containing 1AX & 4DZ should be remain in Tabel 1.
this can be done by subquery
get all MainID from table2 where amt is 0 or null
delete all rows that equal to previous fetched MainID
delete from table1 where MainID in (
select SALESID from table2 where AMT <=0 or AMT is null
)
You can use exists:
delete from table1
where exists (select 1
from table2 t2
where table1.mainid = t2.salesid and
(t2.amt = 0 or t2.amt is null)
);
Thinking an INNER JOIN would be much faster on larger data sets. Something like this:
DELETE
T1
FROM
Table1 T1
INNER JOIN
Table2 T2 ON T2.SalesID = T1.MainID
WHERE
IsNull(T2.Amt,0) = 0

JOIN to get items without value in other table gives multiple results

I have two tables like this:
Table1
ObjectName
ObjectId
Status
Name 1
001
OK
Name 2
002
OK
Name 3
003
Wait
Name 4
004
Wait
Table2
ObjectId
ObjectColor
001
Red
001
Blue
002
Magenta
002
Cyan
003
Blue
003
Green
004
Orange
004
Cyan
Now, I want to query ObjectName of any item with status OK in Table1 and without the color blue in Table2.
The nearest I can come is this:
SELECT
Table1.ObjectName
FROM
Table1
LEFT JOIN Table2 ON Table2.ObjectId = Table1.ObjectId
WHERE
Table1.Status = 'OK'
AND Table2.ObjectColor <> 'Blue'
This results in:
ObjectName
Name 1
Name 2
Name 2
I understand why this doesn't work. But what would be the correct approach?
I expect to only get one instance of Name 2 from this query.
Thanks!
Why join at all? You want data from table1, so select from table1. You want to exclude certain rows, which is why you have a WHERE clause. One restriction is Status = 'OK', the other is that NOT EXISTS 'Blue' for the object in table2.
select objectname
from table1
where status = 'OK'
and not exists
(
select null
from table2
where table2.objectid = table1.objectid
and table2.objectcolor = 'Blue'
);
As there are no nulls involved, you can do the same with the simpler NOT IN:
select objectname
from table1
where status = 'OK'
and objectid not in (select objectid from table2 where objectcolor = 'Blue');
You can use distinct if you just want the unique ObjectName
SELECT
Table1.ObjectName
FROM
Table1
WHERE
Table1.Status = 'OK'
and not exists
(select 1 from Table2 where ObjectColor = 'Blue' and table2.objectid=table1.objectid)
SELECT
Table1.ObjectName
FROM
Table1
JOIN
(
SELECT ObjectId FROM TABLE2 WHERE ObjectColor<>'BLUE'
)X ON Table1.ObjectId=X.OBJECTID
WHERE Table1.Status = 'OK'
You can use below query
At first I have selected the IDs from Table2 whose not have any entry belong to BLUE (SubQuery). After that I just join this result with Table1
SELECT * FROM Table1
Inner Join
(
SELECT Objectid from Table2
group By Objectid
Having SUM(Case when ObjectColor ='Blue' Then 1 else 0 end)=0
) t2
on Table1.Objectid=t2.Objectid
And Table1.status='OK'

How to get Oracle to return unique results in a one to many relationship tables with a left join

I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D

SQL query to display list items

Okay, I am trying to write a query from a poor table structure.
Below is something that I want to achieve:
Table 1: List of Items
T1C1 T1C2
A Fred
B Bart
C Carl
Table 2: Second list of Items
T2C1 T2C2
1 Chocolate
2 Cake
3 Pie
4 Fish
5 Pizza
Table 3: Joining table
T3C1 T3C2 T3C3
1 A Y
4 A Y
5 A N
1 B N
2 B Y
5 B Y
1 C Y
2 C N
3 C Y
Result
Select query based on a person in Table 1.
However if the value is not in Table 3 then R1C4 should default to N
R1C1 R1C2 R1C3 R1C4
1 Chocolate A Y
2 Cake A N
3 Pie A N
4 Fish A Y
5 Pizza A N
I've assumed a few details to come up with the following:
DECLARE #UserId CHAR
SET #UserId = 'A'
SELECT T2.T2C1 AS R1C1,
T2.T2C2 AS R1C2,
COALESCE(T3.T3C2, #UserId) AS R1C3,
COALESCE(T3.T3C3, 'N') AS R1C4
FROM Table2 AS T2
LEFT JOIN Table3 AS T3 ON T3.T3C1 = T2.T2C1 AND T3.T3C2 = #UserId
Assumption: example output is for user Fred.
To ensure that we see all entries from Table2 we use a LEFT JOIN on the link table (Table3).
We have to COALESCE the values for the two records that don't exist in the link table.
Note that this only works if we filter to one user, as per the expected output.
View my SQL Fiddle for full example.
declare #filter varchar(1)
select #filter= T1C1 from Table_1 where T1C2='Fred';
with CteResult (R1C1,R1C2,R1C3,R1C4)as
(select T2C1 as R1C1,T2C2 as R1C2,T3C2 as R1C3, T3C3 as R1C4 from table_2 A
inner join Table_3 B on T2C1 =T3C1
where T3C2=#filter)
select T2C1 as R1C1,T2C2 as R1C2,coalesce(R1C3,#filter) as R1C3,
case when R1C4 is null then 'N' else R1C4 end R1C4
from table_2 A left outer join CteResult B
on B.R1C1=A.T2C1

MySql Select Query

I have 2 tables like this
Table 1
Id f1 f2
1 ABC red,green
2 DEF blue,yellow
Table 2
id color value
1 red r
2 green g
3 blue b
4 yellow y
How Can I get result like this
f1 f2 values
ABC red,green r,g
DEF blue,yellow b,y
Thanks in Advance
Use the GROUP_CONCAT function:
SELECT t1.f1,
t1.f2,
GROUP_CONCAT(t2.value) AS values
FROM TABLE_1 t1
JOIN TABLE_2 t2 ON FIND_IN_SET(t2.color, t1.f2)
GROUP BY t1.f1, t1.f2
Can you adjust the schema? I think it would benefit if you had a mapping table of whatever ABC is to the colors.
EG:
mapping_table
------------
id table1_id table2_id
1 1 1
2 1 2
That way you can easily do a JOIN.