Inner Join and select other columns on that table - sql

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'

Related

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

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

SQL Subquery to get first record

I need to execute a query something like below.
SELECT TO_CHAR(ROWNUM),
A.Name,
B.Order,
(SELECT * FROM (
SELECT ROUND(LAST_ORDER_AMOUNT,5) FROM ORDERS WHERE ID=A.id AND REQUEST_LEVEL='N' ORDER BY O_DATE DESC)
WHERE ROWNUM =1) AS AMOUNT
FROM Table1 A LEFT JOIN Table2 B
ON A.TYPE_CODE = B.ENTITY_TYPE
But this gives me A.ID is invalid error in oracle. I need to get the first record from inner query as it will return multiple records.
Can someone please let me know how can i bind these tables to achieve my goal.
Thank you in advance.
You can rewrite subquery using WITH clause, not exactly sure on syntax but should be something like following.
WITH AmountQuery
AS (
SELECT ID
,ROUND(LAST_ORDER_AMOUNT, 5) AS AmountValue
,ROW_NUMBER() OVER ( ORDER BY O_DATE DESC ) AS RN
FROM ORDERS
WHERE REQUEST_LEVEL = 'N'
)
SELECT TO_CHAR(ROWNUM)
,A.Name
,B.Order
,C.AmountValue
FROM Table1 A
LEFT JOIN Table2 B
ON A.TYPE_CODE = B.ENTITY_TYPE
LEFT JOIN AmountQuery C
ON a.ID = c.ID
AND c.RN = 1
here is SQLFiddle to show how it works.
http://sqlfiddle.com/#!4/696b6/36
Probably, LIMIT will do the job for you selecting just one record from the subquery (It worked for me in MySQL. I do not have Oracle, but I think it may be similar). Try something like this:
SELECT TO_CHAR(ROWNUM),
A.Name,
B.Order,
COALESCE( C.AMOUNT ) as AMOUNT,
FROM Table1 A LEFT JOIN Table2 B
ON A.TYPE_CODE = B.ENTITY_TYPE
LEFT JOIN ( SELECT ROUND(LAST_ORDER_AMOUNT,5) AS AMOUNT FROM ORDERS WHERE REQUEST_LEVEL='N' ORDER BY O_DATE DESC ) C ON C.ID = A.id
group by A.id;

Write correlated subquery in a WHERE Clause as join

I have a query like below:
select
a.id, a.title, a.description
from
my_table_name as a
where
a.id in (select id from another_table b where b.id = 1)
My question is, is there any way I can avoid the subquery in where clause and use it in from clause itself without compromising of performance?
Both of the answers given so far are incorrect in the general case (though the database may have unique constraints which ensure they are correct in a specific case)
If another_table might have multiple rows with the same id then the INNER JOIN will bring back duplicates that are not present in the IN version. Trying to remove them with DISTINCT can change the semantics if the columns from my_table_name themselves have duplicates.
A general rewrite would be
SELECT a.id,
a.title,
a.description
FROM my_table_name AS a
JOIN (SELECT DISTINCT id
FROM another_table
WHERE id = 1) AS b
ON b.id = a.id
The performance characteristics of this rewrite are implementation dependant.
You may use INNER JOIN as:
select
a.id, a.title, a.description
from
my_table_name as a INNER JOIN another_table as b ON (a.id = b.id and b.id = 1)
Or
select
a.id, a.title, a.description
from
my_table_name as a INNER JOIN another_table as b ON a.id = b.id
where b.id = 1
Both the queries may not return the same value for you. You may choose whatever works for you. Please use this as a starting point and not as a copy-paste code.
To express it as a join:
select distinct
a.id, a.title, a.description
from my_table_name as a
join another_table b on b.id = a.id
where b.id = 1
The use of distinct is to produce the same results in case another_table has the same id more than once so the same row doesn't get returned multiple times.
Note: if combinations of id, name and description in my_table_name are not unique, this query won't return such duplicates as the original query would.
To guarantee to produce the same results, you need to ensure that the id's in another_table is unique. To do this as a join:
select
a.id, a.title, a.description
from my_table_name as a
join (select distinct id from another_table) b on b.id = a.id
where b.id = 1

How can you perform a join when also using a comma-separated list of tables in an SQL select statement?

This is evidently correct syntax in SQL Server:
SELECT a.id, b.name
FROM Table1 a, Table2 b
WHERE a.id = b.fk1
So is this:
SELECT a.id, c.status
FROM Table1 a
JOIN Table3 c ON a.id = c.fk2
But this apparently isn't:
SELECT a.id, b.name, c.status
FROM Table1 a, Table2 b
JOIN Table3 c ON a.id = c.fk2
WHERE a.id = b.fk1
I would NOT normally want to construct a query in the third case's style (and really not the first case's either), but it would probably be the path of least resistence in editing some code that's already been written at my company. Somebody used the first form with five different tables, and I really need to work in a sixth table through a JOIN statement, without taking chances of messing up what they already have. Even though I could re-write their stuff outright if I need to, I would really like to know how to do something like in the third case.
Running the code exactly as-is in the examples, the third case gives me this error message:
The multi-part identifier "a.id" could not be bound.
What is syntactically breaking the third case? What simple fix could be applied? Thanks!
I, likewise, would not recommend doing this. But, you can just change the , to a cross join:
SELECT a.id, b.name, c.status
FROM Table1 a cross join Table2 b
JOIN Table3 c ON a.id = c.fk2
WHERE a.id = b.fk1
This code:
SELECT a.id, b.name, c.status
FROM Table1 a, Table2 b
JOIN Table3 c ON a.id = c.fk2
WHERE a.id = b.fk1
is doing a cross join on a and the result of an inner join on b and c. c cannot access any of the fields in a because the join is being performed on b. what you should do is change your query to:
SELECT a.id, b.name, c.status
FROM Table1 a
inner join Table2 b on a.id = b.fk1
inner JOIN Table3 c ON a.id = c.fk2

mysql select query help -- ORDER BY

I'm trying to construct a select query where it will take all the columns of 4 tables and then order and display the results by the column 'name' (the same in all tables). I'm still learning the ropes of MySQL.
I'm finding that because the columns share the name 'name', only the results from the last table are displayed. Is there a way of performing this query which retains all the data from all the tables?
Should I use different column names? It seems easier to share one name since it is the same information in each.
SELECT * FROM table_one, table_two, table_three, table_four ORDER BY...
The four tables not joined, and the structure is different... Some column names are shared (which it looks like I should fix, I still can at this point), but each has a different amount of columns.
Thank you!
If there's no relationship between the four tables, use UNIONs instead:
SELECT a.name
FROM TABLE_ONE a
UNION
SELECT b.name
FROM TABLE_TWO b
UNION
SELECT c.name
FROM TABLE_THREE c
UNION
SELECT d.name
FROM TABLE_FOUR d
ORDER BY name
There's two options here - UNION is slower, because it will remove duplicates - the final list will be a unique list of names. UNION ALL is faster because it doesn't remove duplicates.
To get the columns from the tables as well, use:
SELECT a.*,
b.*,
c.*,
d.*
FROM (SELECT a.name
FROM TABLE_ONE a
UNION
SELECT b.name
FROM TABLE_TWO b
UNION
SELECT c.name
FROM TABLE_THREE c
UNION
SELECT d.name
FROM TABLE_FOUR d) x
LEFT JOIN TABLE_ONE a ON a.name = x.name
LEFT JOIN TABLE_TWO b ON b.name = x.name
LEFT JOIN TABLE_THREE c ON c.name = x.name
LEFT JOIN TABLE_FOUR d ON d.name = x.name
Yes you should use different column names, but to get all data also you can write quesries like this:
SELECT table_one.* t1, table_two.* t2, table_three.* t3, table_four.* t4 FROM table_one, table_two, table_three, table_four ORDER BY...
johnny_n,
You should use
SELECT name as name1, name as name2, name as name3 etc...
Obviously you need to use the correct syntax, but using the AS keyword, will allow you to use the key you want in your query.
If they all share the same name's....
SELECT *
FROM table_one
LEFT JOIN
table_two USING(name)
LEFT JOIN
table_three USING(name)
LEFT JOIN
table_four USING(name)
ORDER BY name