Cartesian join two tables with no records - sql

I have to join Table A (tax related) to Table B (customer related)
I pull at most 1 record but sometimes no record.
Now I need to return the combined record to the user
I though doing a simple Cartesian product would have work
SELECT * FROM TableA, TableB
but that does not work if TableA or TableB is empty
I would do a full outer join but right now do not have anything to join on. I could create temp tables with identity columns and then join on them (since 1 = 1)
But I was looking for a different way?
Thank you

Per your own suggestion, you could use a full outer join to guarantee a row:
select *
TableA a
full outer join
TableB b
on      1=1
To always return at least one row, even if TableA and TableB are emtpy, you could use a fake table:
select *
from (
select 1 as col1
) fake
left join
TableA a
on 1=1
left join
TableB b
on 1=1

Related

SQL - Need to conditionally join based on value in TableB column

I need to know the rows in TABLE A that have join records in TABLE B based a column value in TABLE B, but I also need to return rows in which a row in TABLE A has no match in TABLE B.
It seems like I need a LEFT JOIN and a LEFT OUTER JOIN, so I'm not sure what to do there. I understand how to do each, but don't understand how to do them together.
The schema looks like:
TABLE_A
pk
TABLE_B
pk
a_fk
some_value
I need the joined rows where Table_A has no join record in Table_B OR Table_A has a join record row in Table_B (it can have many) in which some_value does not equal "thisValue"
Thanks.
A Left join is a left outer join. Outer joins preserve one of the tables which is what you are after so good guess.
SELECT *
FROM Table A
LEFT JOIN Table B
ON TableA.Column = TableB.Column
AND B.SomeValue <> 'ThisValue'
All of the rows with a match will have the B information populated all of those without will have nulls in the B data

Optimizing SQL Query - Joining 4 tables

I am trying to join 4 tables. Currently I've achieved it by doing this.
SELECT columns
FROM tableA
LEFT OUTER JOIN tableB ON tableB.address_id = tableA.address_id
INNER JOIN tableC ON tableC.company_id = tableA.company_id AND tableC.client_id = ?
UNION
SELECT columns
FROM tableA
LEFT OUTER JOIN tableB ON tableB.address_id = tableA.gaddress_id
INNER JOIN tableD ON tableD.company_id = tableA.company_id AND tableD.branch_id = ?
The structure of tableC and tableD is very similar. Let's say that tableC contains data for clients. And tableD contains data for client's branch. tableA are companies and tableB are addresses My goal is to get data from tableA that are joined to table B (All companies that has addresses) and all the data from tableD and also from tableC.
This wroks nice, but I am afraid that is would be very slow.
I think you can trick it like this:
First UNION between C,D and only the join to the rest of the query, it should improve the query significantly :
SELECT columns
FROM TableA
LEFT OUTER JOIN tableB ON tableB.address_id = tableA.address_id
INNER JOIN(SELECT Columns,'1' as ind_where FROM tableC
UNION ALL
SELECT Columns,'2' FROM TableD) joined_Table
ON (joined_Table.company_id = tableA.company_id AND joined_Table.New_Col_ID= ?)
The New_Col_ID -> just select both branch_id and client_id in the same column and alias it as New_Col_ID or what ever
In addition you can index the tables(if not exists yet) :
TableA(address_id,company_id)
TableB(address_id)
TableC(company_id,client_id)
TableD(company_id,branch_id)
Why should that be slow? You select client adresses and branch addresses and show the complete result. That seems straight-forward.
You join on IDs and this should be fast (as there should be indexes available accordingly). You may want to introduce composite indexes on
create index idx_c on tableC(client_id, company_id)
and
create index idx_d on tableD(branch_id, company_id)
However: UNION is a lot of work for the DBMS, because it has to look for and eliminate duplicates. Can there even be any? Otherwise use UNION ALL.
Try CTE so that you don't have to go through TableA and TableB twice for the union.
; WITH TempTable (Column1, Column2, ...)
AS ( SELECT columns
FROM tableA
LEFT OUTER JOIN tableB
ON tableB.address_id = tableA.gaddress_id
)
SELECT Columns
FROM TempTable
INNER JOIN tableC
ON tableC.company_id = tableA.company_id AND tableC.client_id = ?
UNION
SELECT Columns
FROM TempTable
INNER JOIN tableD ON tableD.company_id = tableA.company_id AND tableD.branch_id = ?

Joining columns from different tables without duplicating

I have the table TableA with 100 rows in it. It has a column loanid, which may have duplicates.
I need to join with the other table TableB, which has a column loanid, to join with.
But, the loanid in tableB may or may not be in tableA.
So if I take a right join or left join, I want the result to be same as 100.
Since there is a matching and unmatching loanid in both table, there is a chance of result to be not 100 rows, if I do a right join or left join.
From what you describe you want a left join:
select . . .
from tablea a left join
tableb b
on a.loanid = b.loanid;
This keeps every row in tablea along with all matching rows in tableb. From your description, tableb doesn't have duplicates, so this will keep everything in tablea with no duplicates.
If tableb had duplicates and you wanted one arbitrary row, then you can use outer apply:
select . . .
from tablea a outer apply
(select top 1 b.*
from tableb b
where a.loanid = b.loanid
) b;

My attempt at LEFT JOIN isn't producing desired result. Any ideas?

I am seriously suffering from brain dead as I have done this successfully several times in the past.
This time, it isn't working.
I have 2 tables, tableA and tableB
TableA has all the surmons records
TableB has some but not all surmons.
The common key between them is surmonId.
The requirement is to display the surmons from tableB where there is a match between tableA and tableB but at the same time, display ALL the surmons from tableA.
In other words, give me from tableB any records that exist and all the records on tableA.
The lef join query below is only giving me records that exist in tableB.
Select distinct l.surmons from tableB b left join tableA a on b.surmonId = a.surmonId.
There are only 10 surmons on tableB and that's all I am getting.
Where am I messing up?
Thanks a lot in advance
Either switch order of your tables:
SELECT DISTINCT a.surmons
FROM tableA a
LEFT JOIN tableB b
ON a.surmonId = b.surmonId
Or use my favorite, the RIGHT JOIN:
SELECT DISTINCT a.surmons
FROM tableB b
RIGHT JOIN tableA a
ON b.surmonId = a.surmonId
If you want everything from tableA, you need to make the left join from tableA to tableB.
Select distinct a.surmons from tableA a left join tableB b on a.surmonId = b.surmonId

SQL Delete based on condition in join

It is possible to delete records based on a satisfied condition with a join query?
For instance, I have a linking table joining 3 records. The query I have at the moment deletes records from this table where one of the id's isn't IN() an imploded Php array. I've come to realise that the query should only remove records from this table if the id's don't exist in the array and they belong to a certain other table based on the a link to another table.
For SQL Server, the command is slightly different:
DELETE FROM TableA
FROM TableA LEFT OUTER JOIN TableB ON TableA.Column = TableB.Column
WHERE TableB.Column IS NULL
No, that's not a typo, yes, you do need "FROM TableA" twice. At least, you need the second FROM (the first is optional). The following has the advantage that it works for both SQL Server and MySQL:
DELETE TableA
FROM TableA LEFT OUTER JOIN TableB ON TableA.Column = TableB.Column
WHERE TableB.Column IS NULL
I like to use EXISTS clauses for this:
DELETE FROM TableA
WHERE
<<put your array condition here>>
AND NOT EXISTS
(SELECT 1 FROM TableB Where TableB.ID=TableA.ID)
You can use :
DELETE Based on a Join:
DELETE A
FROM TableA AS A
LEFT OUTER JOIN TableB As B ON A.Id = B.TabaleAId
WHERE B.Column IS NULL
Delete With SubQuery:
DELETE
FROM TableA AS A
Where
A.id not in ( Select B.TabaleAId From Tab;eB As B )
or
DELETE FROM TableA
WHERE Not EXISTS
(
SELECT *
FROM TableB As B
Where B.TableAId = TableA.Id
)
DELETE Using Table Expressions:
With A
As
(
Select TableA.*
FROM TableA AS A
LEFT OUTER JOIN TableB As B ON A.Id = B.TabaleAId
WHERE B.Column IS NULL
)
Delete From A
DELETE FROM TableA
LEFT OUTER JOIN TableB
WHERE TableB.Column IS NULL
Will delete the records in tableA that don't have a corresponding record in TableB. Is that like what you are after?
DELETE FROM a
FROM TableA AS a LEFT OUTER JOIN TableB AS b
on a.CALENDAR_DATE = b.CALENDAR_DATE AND a.ID = b.ID
Where b.ID is null
You can first use the select statement and verify your records that you want to delete and then remove the select statement and add Delete FROM tablename with the above query syntax.
The easiest way to Delete based on join is as follow:
1.Write your query using SELECT statement instead of DELETE statement
SELECT COLUMNS
FROM Table1
INNER JOIN Table2 ON Table1.YYY = Table2.XXX
2.Replace SELECT COLUMNS with DELETE FROM TABLE
DELETE FROM Table1
FROM Table1
INNER JOIN Table2 ON Table1.YYY = Table2.XXX
Note that we need to specify FROM twice, one for DELETE part and one for JOIN part.
delete from TableA
where id in
(
select id from TableA
except select id from TableB
)
Which means "delete from tableA where id in table a but not in table b)
Otherwise a Merge statement might help you (when matched/not matched delete etc)
http://technet.microsoft.com/en-us/library/bb510625.aspx