How can I show one element from one of two tables in a column - sql

Table A has the id for a Company of which the name can be either in table B or table C.
What I'm trying to achieve is to show the fetched name in a new column, something like:
SELECT Bank.Name OR Company.Name AS 'CompanyName'
FROM Account
INNER JOIN Company
ON Account.CompanyID = Company.CompanyID OR
Account.CounterpartyID = Company.CompanyID
INNER JOIN Bank
ON Account.CompanyID = Bank.BankID OR
Account.CounterpartyID = Bank.BankID
WHERE ...
Can this work like this or do I need to use multiple SELECTs?
Thanks in advance!

Assumptions:
There will be ONE, or NO rows in TableA or TableB for the company
If there is a row in both TableA and TableB then taking the company name from TableA is acceptable
With those assumptions this code should do the trick:
SELECT A.CompanyId,
COALESCE(B.CompanyName, C.CompanyName)
FROM TableA A
LEFT
JOIN TableB B
ON A.CompanyId = B.CompanyId
LEFT
JOIN TableC C
ON A.CompanyId = C.CompanyId
WHERE TableA.CompanyId = 1234
Essentially what this code is doing is joining the tables together, using a LEFT JOIN so that rows from TableA don't get excluded by the absence of a row in either of TableB or TableC, then using COALESCE to get the first non-NULL value from either of the two tables for the CompanyName column.
The result of the query (if you were using SELECT *) where TableA doesn't contain a row would look a little like this:
Just to give an example of the data the query would be working against.

I would recommend LEFT JOIN. You seem to want names for both the company and the counterparty. That would be two columns and additional joins:
SELECT COALESCE(c.Name, b.Name) AS CompanyName,
COALESCE(cc.Name, bc.Name) AS CounterpartyName,
FROM Account a LEFT JOIN
Company c
ON a.CompanyID = c.CompanyID LEFT JOIN
Bank b
ON a.CompanyID = b.BankID AND
c.CompanyID IS NULL LEFT JOIN
Company cc
ON a.CounterpartyID = cc.CompanyID LEFT JOIN
Bank bc
ON a.CounterpartyID = bc.BankID AND
cc.CompanyID IS NULL
WHERE ...

SELECT
CASE
WHEN EXISTS(
SELECT b.name FROM tableB b WHERE b.name IS NOT NULL
) THEN b.name AS 'CompanyName'
WHEN EXISTS(
SELECT c.name FROM tableC c WHERE c.name IS NOT NULL
) THEN c.name AS 'CompanyName'
END
FROM tableA a
...
Hope this will work for you!

Yes, it can be done with COALESCE() function if you have NULLs, or even IIF() function or CASE expression
Instead of SELECT Bank.Name OR Company.Name AS 'CompanyName' you can do
SELECT COALESCE(Bank.Name, Company.Name) AS CompanyName
OR
SELECT IIF(Bank.Name IS NULL, Company.Name, Bank.Name) AS CompanyName
OR
SELECT CASE WHEN Bank.Name IS NULL
THEN Company.Name
ELSE Bank.Name
END AS CompanyName
If you mean '' then
SELECT CASE WHEN Bank.Name = ''
THEN Company.Name
ELSE Bank.Name
END AS CompanyName

Related

How to find differences between 2 tables with different key names

So say I have 2 tables. TableA has keys FirstName, LastName, Age, Location. TableB has keys 1FirstName, 1LastName, 1Age, 1Location. Table A is a working table, and TableB is a reference table. How could I go about finding what records exist in TableB that DO NOT exist in TableA
Using an outer join will join all rows of left table to either right table or NULL
Then including only NULL from right hand side will give you what you need.
TableB as left side
SELECT
*
FROM (
SELECT
b.*,
a.*
FROM TableB b
LEFT OUTER JOIN TableA a
ON
b.1FirstName = a.Firstname
AND
b.1LastName = a.Lastname
AND
b.1Age = a.Age
AND
b.1Location = a.Location
) q
WHERE q.FirstName IS NULL

Outer join not showing extra entries

I have made a query in which 3 tables are used. The first table has all the desired names which I need. The 2nd and 3rd table give me those names on which there is some bill amount. But I need all the names from the 1st table as well.
SELECT a.name,
nvl(c.bill_amount,0)
FROM table_1 a left outer join table_2 b
ON a.name = b.name
left outer join table_3 c on B.phone_number = C.phone_number
AND B.email = C.email
where b.status = 'YES'
and a.VALID = 'Y';
Now, the tables b and c give me limited number of names, lets say 5 on which bill is there. But in table_1, there are 10 names. I want to display them also with 0 bill_amount on their name. I'm using Oracle.
Applying a where clause on the right hand tale basiically makes it an inner join. To keep it OUTER, put the condition in the join conditions
Try:
SELECT a.name,
nvl(c.bill_amount,0)
FROM table_1 a
left outer join table_2 b
ON a.name = b.name
and b.status = 'YES' -- Put it here
left outer join table_3 c
on B.phone_number = C.phone_number
AND B.email = C.email
where a.VALID = 'Y'; -- Only items from the left hand table should go in the where clause
The answer above is right , I would just want to be more precise. The fact is when a left join does not match, the column of the right hand table are set to NULL.
Actually NULL is always propagating value in SQL, so b.status = 'YES' have the value NULL if the join does not math, and then the predicate does not match neither.
The general way to handle this would be (b.status = 'YES' or b.name IS NULL) : because b.name is the join column it is null if and only if join does not match, which may not be the case for b.status.
Because NULL is propagating you cannot use field = NULL but field IS NULL instead.
But it is okay to have it in the join clause when it is more clear.

Inner Join and select other columns on that table

This is a part of my query and I have a union before this query. I want to select more column in table1 under a condition.
SELECT c.ID, c.Name, c.Position, c.Email, c.ContactNumber
FROM table1 c
INNER JOIN table2 a
ON c.ID = (SELECT foreignID FROM table2 WHERE a.Name = 'someName')
WHERE Dept = 'Something' --this will return nothing since in the inner join
--the condition returns a single column and it doesn't
--satisfy the WHERE Clause
I want to select the person that satisfies the ID (which works), including the people with a Dept of Something. Is there another way in solving this, or I really need to use UNION for this. Will this affect the performance of an App, specifically Mobile App?
If I Understood your requirement correctly then Use LEFT JOIN
SELECT c.ID, c.Name, c.Position, c.Email, c.ContactNumber
FROM table1 c
LEFT JOIN table2 a ON c.ID = a.foreignID AND a.Name = 'someName'
WHERE Dept = 'Something'

SQL Query efficiency (JOIN or Cartesian Product )

Hello I am Confused with three scenarios which commonly every one use in almost every project.
I wanted to Know which one of these will be Efficient accordinng to - Less Time Complexity - Efficiency - effectiveness
TableA (userid ,username, email , phone)
TableB (username,TestField)
.
Case 1
select email, TestField from TableA , TableB
where TableA.username = TableB.username and
TableB.username = 'ABC'
group by email, TestField
Case 2
select email, TestField from TableA
inner join TableB on TableB.username = 'ABC'
Case 3
declare #uname nvarchar(20);
set #uname = 'ABC';
declare #Email nvarchar(20);
select #Email= email from TableA where username = #uname;
select #Email as email , TestField from TableB
where username = #uname
Case 2 will give you a different output anyway, as you are not joining TableA and TableB in any way so you get a Cartesian product.
Since all of a sudden email came up, you will need a join in case 1:
In Case 1 you can simply rewrite the query to
SELECT DISTINCT A.Email , B.TestField
FROM TableA A join TableB B on A.username = B.Username
WHERE B.username = 'ABC'
Which is more readable and easier to maintain as you do not ave a superfluous GROUP BY clause.
In Case 3 you have userId in your where clause, which is not even in your tableB according to your post.
In general, for maintainability and readibility:
Use explicit joins
SELECT * FROM A JOIN B ON A.id = B.id
is preferable over
SELECT * FROM A, B WHERE A.id = B.id
And use DISTINCT when you want distinct values, instead of GROUP BY over all columns:
SELECT DISTINCT a, b, b FROM TABLE
is preferable over
SELECT a, b, c FROM TABLE GROUP BY a, b, c
Most database experts will tell you that cross products are evil and to be avoided. Your first example would work just fine. It is an implicit inner join.
Your second example is syntactically incorrect. I suspect you'd get an error from MSSQL Server Manager. What you probably meant was:
select a.email, b.TestField
from TableA a inner join TableB b
on (b.username = a.username)
where b.username = 'ABC'
Your first example will probably be the more efficient, since MSSQL Server is smart enough to do the projection on TableB.username before doing the join. I'm not so certain that this would be the case in the above version of case 2.
To be sure you could do it like this:
select a.email, b.TestField
from TableA a inner join
(select * from TableB where TableB.username = 'ABC') b
on (b.username = a.username)
where b.username = 'ABC'
Hope that helps.

Select field from table a if it exists, if it doesn't select field from table b

SELECT a.amount, CASE When d.name <> NULL Then d.name Else c.name End As 'name'
from a
JOIN b on a.id= b.id
LEFT JOIN c on a.tokenId = c.tokenId
LEFT JOIN d on a.tokenId = d.tokenId
I'm attempting to select the name from table d if it exists, and if it doesn't, select it from table c. The name field comes back as NULL, however I know they are not null in either of the tables.
Can anyone help me get this solved?
You can't use the <> operator to compare with null. Use the is operator:
SELECT a.amount, CASE When d.name is not null Then d.name Else c.name End As 'name'
You can also use the coalesce function:
SELECT a.amount, coalesce(d.name, c.name) As 'name'
Use COALESCE:
SELECT a.amount, COALESCE(d.name,c.name) "name"
from a
JOIN b on a.id= b.id
LEFT JOIN c on a.tokenId = c.tokenId
LEFT JOIN d on a.tokenId = d.tokenId