Finding all records that do NOT join on inner join of two tables? - sql-server

I have a SQL Server query for an inner join...
SELECT *
FROM tableA
INNER JOIN tableB on tableA.my_id = tableB.my_id
How would I find all the records that did NOT match in this join?

You can use a FULL JOIN to combine the two tables, then use a WHERE clause to filter the results down to only non-matching rows by checking for a NULL in each tables primary key value.
Full outer join All rows in all joined tables are included, whether they are matched or not.
SELECT a.pk, b.pk
FROM tableA a
FULL JOIN tableB b ON a.pk=b.fk
WHERE
a.pk IS NULL
OR b.pk IS NULL

SELECT A2.* FROM TableA A2
WHERE A2.my_id NOT IN
(Select tableA.my_id FROM
tableA
inner join
tableB
on tableA.my_id = tableB.my_id)
you could similarly do the above starting SELECT B2.* FROM TableB B2, in order to separately query unmatched records in Table B
if you want all records in one table you could UNION ALL the two queries, depending on the table field structures being the same or how you specify the fields you select - what are you doing with the data?

SELECT * FROM tableA where my_id NOT IN (SELECT my_id from tableB)
UNION ALL
SELECT * FROM tableB where my_id NOT IN (SELECT my_id from tableA)

Related

SQL Join Multiple columns in one table with one column in another table

I got two tables as below
table 1 :Which got multiple columns which refers to a value in the second table.
tbale2:Lookup table where it got a row for every possible value for the columns in the above table
What I want to do is lookup the values in columns ItemID,ORDIG,CatID,MediaID in table 1 from ValueID in table2 and return ValueName
so at the end my result should look like
ItemID OrgID CatID MediaID
i859049 Singapore Full 0001edf
You will need to join to the lookup table once for each value you need, but should likely need to use a LEFT instead of INNER join since the values may be null.
SELECT
T1.ItemId,
Items.ValueName AS ItemName,
T1.OrgID,
Orgs.ValueName AS OrgName,
T1.CatID,
Cats.ValueName AS CatName,
T1.MediaID,
Media.ValueName AS MediaName
FROM Table1 T1
LEFT OUTER JOIN Table2 Items
ON T1.ItemId = Items.ValueID
LEFT OUTER JOIN Table2 Orgs
ON T1.OrgId = Orgs.ValueID
LEFT OUTER JOIN Table2 Cats
ON T1.CatId = Cats.ValueID
LEFT OUTER JOIN Table2 Media
ON T1.MediaId = Media.ValueID

Merging two columns with values from another table

I have similar table
How can i merge these two tables ? There are other columns, but these are the same.
How can i fill Table1 with values of Table2 or merge these tables ?
In Table2 is only 1 customer.
So the result table will have all customers with their values (Table1 will have Customer4 with Sales 50).
Thank you.
To update the table do
update t1
set t1.sales = t2.sales
from table1 t1
join table2 t2 on t1.customername = t2.customername
and as a select use
select t1.customername,
coalesce(t1.sales, t2.sales) as sales,
t1.date,
t1.variable1
from table1 t1
left join table2 t2 on t1.customername = t2.customername

How do I name the results of a joined table query

I have two tables and did an inner join on them based on id. Now I need to name this joined table. How do I do that? The reason I want to name this table is because I have to join this result table with some other tables.
You created what is commonly referred t as a relvar, not another table. You can join to it by placing it's SELECT definition in a sub query like this:
SELECT
FROM (
-- original join SQL
) t
INNER JOIN table2 on ...
You can create an alias for the result of a join using a subquery. For example:
select *
from (
select *
from tbl1
join tbl2
on tbl1.id = tbl2.id
) as JoinAlias
join tbl3
on JoinAlias.id = tbl3.id
You can often make do without such an alias. For example, consider a third join:
select *
from tbl1
join tbl2
on tbl1.id = tbl2.id
join tbl3
on tbl3.col1 = tbl1.col1
and tbl3.col2 = tbl2.col2
As you can see, the third join's condition can refer to columns from all earlier tables.
select * from (
select * from TableA a join TableB b on a.id = b.a_id
) as p;
As per the comments, it seems that a view might be what you are looking for:
create view MyView
as
select * from TableA a join TableB b on a.id = b.a_id;
It won't be listed in the tables (rather in the views), but will behave just like a table in your sql editor.

Join two tables only if the first contains certain values if not join another

I am trying to write a query that join to a TableA another TableB if TableA.Column1 contains numeric values and Join to TableA another TableC if TableA.Column1 contains varchar values.
Is there a way to write such a query?
How about something like this? You will need to cast the columns appropriate to some middle ground.
SELECT *
FROM TableA a
INNER JOIN TableB b ON b.Columns1 = a.Column1
AND ISNUMERIC(a.Column1) = 1
WHERE 1=1
UNION
SELECT *
FROM TableA a
INNER JOIN TableC c ON c.Columns1 = a.Column1
AND ISNUMERIC(a.Column1) = 0
The table design sounds questionable, but I think this query is a simple way to achieve what you're asking for.
SELECT
TableA.Column1,
TableB.Column2,
TableC.Column2,
ISNULL(TableB.Column2, TableC.Column2)
FROM TableA
LEFT OUTER JOIN TableB ON
ISNUMERIC(TableA.Column1) = 1
AND TableA.Column1 = TableB.Column1
LEFT OUTER JOIN TableC ON
ISNUMERIC(TableA.Column1) = 0
AND TableA.Column1 = TableC.column1
As Mike Cheel points out, you may need to do some casting.
Also, with this approach you will need to consider the possibility that there is a record in TableA that does not match anything in TableB or TableC, because this is using outer joins. If you don't want those records in your result, you can just exclude them with a condition in your WHERE clause.
Along the lines of JNK's comment, here's a way where you could go about it which at least tries to encapsulate the design issue a bit, by add 2 Computed columns to your table, which represent placeholders for the INT and VARCHAR foreign keys.
ALTER TABLE MyTable ADD IntJoinColumn AS
CASE WHEN ISNUMERIC(BadJoinColumn) = 1
THEN CAST(BadJoinColumn AS INT)
ELSE NULL
END;
ALTER TABLE MyTable ADD VarCharJoinColumn AS
CASE WHEN ISNUMERIC(BadJoinColumn) = 1
THEN NULL
ELSE BadJoinColumn
END;
You can then join in a more 'readable' manner, like so:
SELECT mt.*
FROM MyTable mt
INNER JOIN MyIntJoinTable ON IntJoinColumn = MyIntJoinTable.Id
UNION ALL
SELECT mt.*
FROM MyTable mt
INNER JOIN MyVarCharJoinTable ON VarCharJoinColumn = MyVarCharJoinTable.VarCharId;
SQLFiddle Here
(The NULL mapping has the effect of filtering out the 'incorrect' data types by eliminating them during the INNER JOIN.)

SQL Server SELECT statement

I need a query that returns rows from table A if value X in table A is not the same as the sum of value Y from corresponding row(s) in table B. The issue is that there may or may not be rows in table B that correspond to the rows in table A, but if there no rows in table B, then the rows from table A should still be returned (because there is not a matching value in table B.) So it is like a LEFT OUTER join scenario, but the extra complication of having a comparison as an additional selection criteria.
I have a query that does the opposite, ie. returns rows if the value in table A is the same as the value of row(s) in table B, but sadly this isn't what I need!
SELECT TableA.id, TableA.bdate
FROM TableA
LEFT JOIN TableB ON TableB.ID = TableA.id
WHERE TableA.select_field = 408214
AND TableA.planned_volume =
(select sum(actual_volume)
from
TableB
where TableB.id = TableA.id)
ORDER BY TableA.id
Any help greatly appreciated.
How about something like this:
SELECT TableA.Id, TableA.bdate
FROM TableA
LEFT JOIN
(
SELECT Id, SUM(actual_volume) AS b_volume
FROM TableB
GROUP BY Id
) AS TableBGrouping
ON TableBGrouping.Id= TableA.Id AND TableA.planned_volume <> b_volume
ORDER BY TableA.Id
WITH TotalVolumes
AS
(
SELECT id, SUM(actual_volume) AS total_volume
FROM TableB
GROUP
BY id
)
SELECT id, bdate, planned_volume
FROM TableA
EXCEPT
SELECT A.id, A.bdate, T.total_volume
FROM TableA AS A
JOIN TotalVolumes AS T
ON A.id = T.id;
SELECT TableA.id, TableA.bdate
FROM TableA
LEFT JOIN TableB ON TableB.ID = TableA.id
AND TableA.planned_volume <>
(select sum(actual_volume)
from
TableB
where TableB.id = TableA.id)
ORDER BY TableA.id

Resources