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

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'

Related

SQL select units with condition of another column

I have this
ID
Product
001
A
001
B
001
C
002
A
002
A
002
D
003
G
003
D
003
C
004
G
004
D
004
R
and I wand ID list if they don't have product C...so:
002
You can apply the set difference between all ids and all ids with a "c" with the standard way of doing it: using the NOT IN operator in the WHERE clause.
SELECT DISTINCT ID
FROM tab
WHERE id NOT IN (SELECT ID FROM tab WHERE Product = 'C')
Consider below query:
SELECT DISTINCT ID FROM (
SELECT *, COUNTIF(product = 'C') OVER (PARTITION BY ID) AS cnt_C
FROM sample_table
) WHERE cnt_C = 0
output:
There are multiple ways of doing this, but I think a very readable way is to use NOT EXISTS.
SELECT DISTINCT id
FROM mytable t1
WHERE NOT EXISTS (SELECT 1 FROM mytable t2 WHERE t2.id = t1.id AND t2.Product = 'C')
The WHERE clause checks that there is no row with product C and the same id. The DISTINCT ensures you don't get multiples of the same id returned.
I am not sure but I think you just need a normal where
SELECT * FROM table_name WHERE product != product_name
*insert the table name in the place of Table_name and product name in the place of product_name
select distinct
id
from
your_table_name
where
product <> 'C';
This will return you list of ID's that don't have product C

Same column name from two tables satisfying two conditions

I need some quick help on SQL. This is basic for most I am sure.
I want to select orderId in both tables merged that satisfies status = 1.
Please find example of the two table tb1 and tb2 here:
tb1
orderId status
---------------
001 0
003 1
005 1
007 1
...
tb2
orderId status
----------------
002 1
008 1
004 0
Use this query:
SELECT
tb1.OrderId,
tb1.Status
FROM
tb1
WHERE
tb1.status = 1
UNION
SELECT
tb2.OrderId,
tb2.Status
FROM
tb2
WHERE
tb2.status = 1;
You can use UNION ALL.
Your query would be:
SELECT *
FROM (
SELECT *
FROM tb1
UNION ALL
SELECT *
FROM tb2
) a
WHERE STATUS = 1

SQL | Left Join when 2nd Table Has No Matching Row?

I need to be able to show results for a row that doesn't actually exist in a second table. I have tried left join, but it doesn't seem to work for what I need to do. I have 2 tables, for example:
Table1
NAME | KEY
John 12345
Frank 23456
Table2
KEY | LIST | STATUS
12345 10001 1
12345 10003 0
23456 10001 1
23456 10002 1
I need to be able to show results like this :
NAME | KEY | LIST | STATUS
John 12345 10001 1
John 12345 10002 (null)
John 12345 10003 0
Frank 23456 10001 1
Frank 23456 10002 1
Frank 23456 10003 (null)
But I can't figure out how to do this because the records that would return a null value don't actually exist in the second table. If I run them one at a time, I can kind of get the results I need by doing a UNION ALL, but this is not efficient (I also had to re-order my results, which is making it harder as well)
SELECT b.list, a.name, a.key, b.status
FROM table1 a JOIN table2 b ON a.key = b.key
WHERE a.name = 'John'
UNION ALL
SELECT distinct(b.list), NULL AS "a.name", NULL AS "a.key", NULL AS "b.status"
FROM table2 b
This isn't an ideal solution either because I'm pulling the rest of the lists, but the other fields end up being null, so I have to paste them in manually when I move my results to excel.
Any ideas? I really thought I should be able to do this with a left join, but nothing I'm doing seems to work.
Use a cross join to get all the rows. Then use left join to bring in the existing values:
select t1.key, l.list, t2.status
from table1 t1 cross join
(select distinct list from table2) l left join
table2 t2
on t1.key = t2.key and t1.list = t2.list;
Try FULL OUTER JOIN
Example:
SELECT A.NAME, A.KEY, A.LIST, B.STATUS
FROM Table1 A
FULL OUTER JOIN Table2 B
ON A.KEY = B.KEY AND A.LIST = B.LIST
If don't want rows of the second table that they have not a reference in the first table add the condition:
WHERE A.KEY IS NOT NULL
Here is what I came up with. The first two queries are used to get all possible combinations of NAME, KEY and LIST together. The final query joins back to Table2 to get STATUS, returning NULL where STATUS does not exist.
;WITH Lists
AS
(
SELECT DISTINCT LIST
FROM Table2
),
KeyList AS
(
SELECT [NAME], [KEY], [LIST]
FROM Lists CROSS JOIN Table1
)
SELECT a.[NAME], a.[KEY],A.[LIST],b.[STATUS]
FROM KeyList a
LEFT JOIN Table2 b
ON a.[KEY] = b.[KEY]
AND a.[LIST] = b.[LIST]

One select on two tables with NULL and not null

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

SQL Server - How to display values that differ in two similar tables

I have 2 tables in SQL Server (ver:2008). Both tables have similar structure. Second table has few extra columns. I want to write a query that displays the differences in these tables (for matching fields). Output should display columns from both tables side by side (for comparison).
I tried using EXCEPT which is displaying the results from table 1 that don't match the results in table2. But I need to display both results side-by-side.
Thank you.
You simply need to select the fields you wish to display:
select t1.*, t2.*
from table1 t1
inner join table2 t2 on t1.ID = t2.ID
where t1.field1 <> t2.field1 OR t1.field2 <> t2.field2
OR ...
For example, if you have 2 tables, Products1 and Products2, both with columns Name, Price, Color etc., and you want to list all different products, you can use this:
SELECT Name FROM Products1
UNION
SELECT Name FROM Products2
OR, you can use FULL JOIN keyword, it returns rows when there is a match in one of the tables. For example:
The “Cars” table:
P_Id Name Color Quality City
---- -------- ----- ------- -----------
1 BMW Red good Las Vegas
2 Lexus Blue bad Los Angeles
3 Mercedes Green good MIami
The "Orders" table:
O_Id OrderNo P_Id
---- ------- ----
1 123 3
2 234 3
3 345 1
4 456 1
5 689 18
Now we want to list all the cars and all the people with their orders.
We use:
SELECT Cars.Name, Cars.Color, Orders.OrderNo
FROM Cars
FULL JOIN Orders
ON Cars.P_Id=Orders.P_Id
ORDER BY Cars.Name
The result:
Cars Color OrderNo
-------- ----- -------
BMW Red 345
BMW Red 456
Mercedes Green 123
Mercedes Green 234
Lexus Blue -
- - 689
Give this a shot. It assumes that there's one column (a) that is identical between the tables, and the rest (b, c, ...) are potentially different.
SELECT t1.a, t2.a, t1.b, t2.b, t1.c, t2.c, ...
FROM table1 t1
JOIN table2 t2
ON t1.a = t2.a
AND NOT (t1.b = t2.b AND t1.c = t2.c ...)
SELECT * FROM
(
SELECT * FROM TABLE1
EXCEPT
SELECT * FROM TABLE2
) T1
UNION ALL
SELECT * FROM
(
SELECT * FROM TABLE2
EXCEPT
SELECT * FROM TABLE1
) T2