SQL to select distinct values from table with foreign key - sql

I have two tables: A (a_id as int, some string fields...) and B (b_id, string field "name" and referenced column a_id).
I want to select unique values from the table A where B.name LIKE "%somestring%".

You could use EXISTS:
SELECT a.*
FROM TableA a
WHERE EXISTS
(
SELECT 1 FROM TableB b
WHERE a.a_id = b.a_id
AND b.name LIKE "%somestring%"
)

you can use inner join to do this.
select A.a_id, B.b_id, from A inner join B on A.a_id = B.a_id where B.Name LIKE '%somestring%'

Related

Compare two tables via the three tables SQL

I plan to compare two tables via the three table. my query is as the following
Select count(*)
from tableA a
join tableB b
on a.A_ID =b.A_ID
full join tableC c
on c.B_ID=b.B_ID
where a.A_ID is null or c.B_ID is null
if the count is zore, then the tableA and TableC match, otherwise, these two tables do not match
It takes a long time to run the query. Do we have a way to compare tableA and tableC fast?
Question: How to compare tableA and tableC?
You don't need a FULL JOIN here, you can just join the first two tables, then EXCEPT the third.
SELECT COUNT(*)
FROM (
SELECT b.B_ID, a.A_Name
FROM tableA a
JOIN tableB b ON a.A_ID = b.A_ID
EXCEPT
SELECT c.B_ID, c.B_Name
FROM tableC c
) t;
Note that EXCEPT implies DISTINCT so if you want the number of rows extra in table_A then you need to use WHERE NOT EXISTS
SELECT b.B_ID, a.A_Name
FROM tableA a
JOIN tableB b ON a.A_ID = b.A_ID
WHERE NOT EXISTS (SELECT 1
FROM tableC c
WHERE c.B_ID = b.B_ID AND c.B_Name = a.A_Name
);
If you want to find rows that are in one table but not the other you can use the EXCEPT union in standard SQL
-- Show in A not in B
SELECT * FROM TableA EXCEPT SELECT * FROM TableB
-- Show in A not in C
SELECT * FROM TableA EXCEPT SELECT * FROM TableC
-- Show in B not in A
SELECT * FROM TableB EXCEPT SELECT * FROM TableA
-- Show in B not in C
SELECT * FROM TableB EXCEPT SELECT * FROM TableC
-- Show in C not in A
SELECT * FROM TableC EXCEPT SELECT * FROM TableA
-- Show in C not in B
SELECT * FROM TableC EXCEPT SELECT * FROM TableB

SQL Server-Conditional Join

I have two tables that I want to conditionally join.
Basically, when the Type column from table A ='First' then table A should join to table B on a.ID = b.ID COLLATE Latin1_General_100_CS_AS, but when the Type column from table A ='Second' then table A should join to table B on a.Name = b.Name.
I am putting dummy data below so that you can get a sense of what I am trying to accomplish.
You can use ored conditions:
select a.*, b.amount
from tablea a
inner join tableb b
on (a.type = 'First' and b.id = a.id)
or (a.type = 'Second' and b.name = a.name)

Need help using a nested join

I need to join an ID# field from tableA to the ID# field in tableB so I can join the NAME field in tableB to the NAME field in tableC. Currently using CTE's and I would like to accomplish this without the need of a CTE.
Currently doing:
WITH t
AS
(
SELECT tableB.ID#
FROM tableA
INNER JOIN tableB ON (tableA.ID_REF# = tableB.ID_REF#)
),
u as
(
SELECT NAME
FROM tableC
)
SELECT u.NAME
FROM t
INNER JOIN u ON (t.ID# = u.ID#)
I'm assuming I'm able to do the same thing with a nested join?
join an ID # field from tableA to the ID # field in tableB so I can join the NAME field in table B to the NAME field in tableC.
Why use CTEs? Just chain the JOINs:
SELECT . . . -- whatever you want here
FROM tableA a JOIN
tableB b
ON a.ID_REF# = b.ID_REF# JOIN
tableC c
ON b.Name = c.Name;
Indeed, you don't need a CTE - you can join twice. Based on your problem statement, that would be:
select c.name
from tableC c
inner join tableB b on b.name = c.name
inner join tableA a on a.id# = b.id#
Inner join outputs the same result no matter the order of join ( a -> b -> c, c -> b -> a). Also note that default join without any keyword will be inner join.
So you can do like this (c->a->b):
select ...
from tableC c
join tableB b on b.name = c.name
join tableA a on a.ID_REF# = b.ID_REF#
or this (a->b->c):
select ...
from tableA a
join tableB b on a.ID_REF# = b.ID_REF#
join tableC c on b.name = c.name
Declare #TableA table (ID int ,Name nvarchar(50))
Declare #TableB table(ID int, Name nvarchar(50))
Declare #TableC table (ID int , Name nvarchar(50))
insert into #TableA values(1,'Chit'),(2,'Mar'),(3,'Thiri')
insert into #TableB values(1,'Chit'),(2,'Mar'),(3,'Thiri')
insert into #TableC values(1,'Chit'),(2,'Mar'),(3,'Thiri')
select c.ID,c.Name from #TableC c inner join (select b.Name from #TableA a inner join #TableB b on a.ID =b.ID Group by b.Name) bb on bb.Name=c.Name

XOR JOIN in SQL

I have the following tables
Table A
ID "Other Columns"
1
2
3
Table B
ID "Other Columns"
3
4
5
What is the efficient way to return the below result?
Result
ID "Other Columns"
1
2
4
5
A full outer join should work, and only go through each table once. They can be tricky, so test carefully!
SELECT
isnull(A.ID, B.ID) ID
,"Other columns" -- Handle nulls properly!
from TableA A
full outer joing TableB B
on B.ID = A.ID
where not (A.ID is not null
and B.ID is not null)
You want to use left and right join and union them
Select TableA.ID as 'ID','Other Colums'
FROM TableA Left join TableB
ON TableA.ID=TableB.ID
WHERE TableB.ID IS NULL
UNION
Select TableB.ID as 'ID','Other Colums'
FROM TableA Right join TableB
ON TableA.ID=TableB.ID
WHERE TableA.ID IS NULL
You can try like this
SELECT
COALESCE(a.id, b.id),
OtherColumns
FROM #tablea a
FULL JOIN #tableb b
ON a.id = b.id
WHERE a.id IS NULL
OR b.id IS NULL
You can do this with a UNION ALL using a LEFT JOIN to determine if the ID is not in the other table. Keep in mind that the column count and datatypes between the two tables must match up:
Select A.Id, A.OtherColumns
From TableA A
Left Join TableB B On A.Id = B.Id
Where B.Id Is Null
Union All
Select B.Id, B.OtherColumns
From TableB B
Left Join TableA A On A.Id = B.Id
Where A.Id Is Null
Not quite sure what you need with the "Other columns", but you could use EXCEPT:
Select ID from TableA
EXCEPT
Select ID from TableB
If you need Other columns from TableA you could use:
Select ID, OtherColumn1, OtherColumn2 from TableA
where ID not in (select ID from TableB)
(as long as ID cannot be null in TableB)
I broke down each part to be clearer!
select *
into #temp
from
TabA Full outer join TabB
on TabA.ColNameA = TabB.ColNameB
select *
into #temp2
from #temp
where (ColNameA is Null Or ColNameB is null)
select ColNameA from #temp2
where ColNameA Is not null
union
select ColNameB from #temp2
where ColNameB Is not null

sql - multiple layers of correlated subqueries

I have table A, B and C
I want to return all entries in table A that do not exist in table B and of that list do not exist in table C.
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
this gives me the first result of entries in A that are not in B. But now I want only those entries of this result that are also not in C.
I tried flavours of:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
where not exists (select 1 from table_C as c
where a.id = c.id)
But that isnt the correct logic. If there is a way to store the results from the first query and then select * from that result that are not existent in table C. But I'm not sure how to do that. I appreciate the help.
Try this:
select * from (
select a.*, b.id as b_id, c.id as c_id
from table_A as a
left outer join table_B as b on a.id = b.id
left outer join table_C as c on c.id = a.id
) T
where b_id is null
and c_id is null
Another implementation is this:
select a1.*
from table_A as a1
inner join (
select a.id from table_A
except
select b.id from table_B
except
select c.id from table_c
) as a2 on a1.id = a2.id
Note the restrictions on the form of the sub-query as described here. The second implementation, by most succinctly and clearly describing the desired operation to SQL Server, is likely to be the most efficient.
You have two WHERE clauses in (the external part of) your second query. That is not valid SQL. If you remove it, it should work as expected:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
not exists (select 1 from table_C as c -- WHERE removed
where a.id = c.id) ;
Tested in SQL-Fiddle (thnx #Alexander)
how about using LEFT JOIN
SELECT a.*
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
LEFT JOIN TableC c
ON a.ID = c.ID
WHERE b.ID IS NULL AND
c.ID IS NULL
SQLFiddle Demo
One more option with NOT EXISTS operator
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM (SELECT b.ID
FROM dbo.test72 b
UNION ALL
SELECT c.ID
FROM dbo.test73 c) x
WHERE a.ID = x.ID
)
Demo on SQLFiddle
Option from #ypercube.Thank for the present;)
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM dbo.test72 b
WHERE a.ID = b.ID
UNION ALL
SELECT 1
FROM dbo.test73 c
WHERE a.ID = c.ID
);
Demo on SQLFiddle
I do not like "not exists" but if for some reason it seems to be more logical to you; then you can use a alias for your first query. Subsequently, you can re apply another "not exists" clause. Something like:
SELECT * FROM
( select * from tableA as a
where not exists (select 1 from tableB as b
where a.id = b.id) )
AS A_NOT_IN_B
WHERE NOT EXISTS (
SELECT 1 FROM tableC as c
WHERE c.id = A_NOT_IN_B.id
)