why to use same table alias and do SELF JOIN - sql

I have one sql script in that one table is used with two alias and make a JOIN on it
but I need to understand why and when it is needed to do so
please elaborate ?
SELECT
ISNULL(MarketValue,0)
FROM
(
SELECT TOP 5
Delta,
MarketValue
FROM
(
SELECT DISTINCT
FormatNumber(SUM([CURRENT].MarkToMarket), 0, ',', 0) AS Delta,
AVG([CURRENT].Mark) * SUM([CURRENT].Position) AS NumericPosition,
FormatNumber(AVG([CURRENT].Mark) * SUM([CURRENT].Position)* CASE WHEN [CURRENT].SecurityType IN ('Equity','Equity Option') THEN 100 ELSE 1 END, 0, ',', NULL) AS MarketValue
FROM
NAV [CURRENT]
LEFT JOIN
NAV Compare ON
[CURRENT].PurchaseLotId = Compare.PurchaseLotId AND
Compare.Date = '2012-06-06'
WHERE
[CURRENT].SecurityType not in ('Equity')
GROUP BY
ORDER BY
NumericDelta DESC
) Movers
FOR XML PATH ('TR'), TYPE
) AS VARCHAR(MAX)
)
Why it is used like FROM
NAV [CURRENT]
LEFT JOIN
NAV Compare ON
[CURRENT].PurchaseLotId = Compare.PurchaseLotId AND
Compare.Date = '2012-06-06'
NAV is only one table then what is the purpose to do take two alias of same table NAV [CURRENT] and NAV Compare and use LEFT JOIN?
please elaborate me.

You are comparing 2 records from the table
You need two different alias's to represent the two different records.
So for example if you had a table called Employees: (Id, Name, ManagerId) where ManagerId is the Id of an Employee's immediate manager
ID Name ManagerId
1 CEO null
2 YourBoss 1
3 You 2
and you wanted to run a query that selected you and the name of your boss:
SELECT emp.Name, mgr.Name
FROM Employees emp INNER JOIN Employees mgr on emp.ManagerId = mgr.Id
WHERE emp.Id = 3

NAV is being joined with itself, so there are actually two instances of every column in nav. Current and compare are used to differentiate between them.

Related

SQL join based on select as column name

So in one table I can use a replace and charindex to extract a specific ID that relates to a PK in another table, I want to then join the data from the other table based on the trimmed value, how can I do this?
select top 100 *, Replace(Left(LogValue,Charindex(';', LogValue) - 1) ,'RtaId=', '') as TaskID, PrmRoutingTask.*
from SytLog
inner join PrmRoutingTask on RtaId = TaskID
where LogTableName like '%Routing%' and LogValue like '%RtaAniId=397%'
order by 5 desc;
The problem I get is that the temp column name I create (TaskID) is not working in the inner join where in fact the results of TaskID have the reference to the RtaId in the RoutingTask table.
Assuming LogValue belongs to the first table you can use the column named TaskID if you produce a subquery as a table expression of the main query.
For example you can produce the column in the table expression a by doing:
select top 100
a.*,
PrmRoutingTask.*
from (
select *,
Replace(Left(LogValue,Charindex(';', LogValue) - 1) ,'RtaId=', '') as TaskID
from SytLog
) a
inner join PrmRoutingTask on PrmRoutingTask.RtaId = a.TaskID
where LogTableName like '%Routing%'
and LogValue like '%RtaAniId=397%'
order by 5 desc

SELECT and JOIN to return only one row for each employee

I have a user table that stores the employeeId, lastName, firstName, department, hire date and mostRecentLogin.
I have another table that stores the employeeId, emailAddress.
The emailAddress table can have multiple rows for an employee if they have multiple email addresses.
I'm trying to return results that only show one row for each employee. I don't care which email address, just as long as it only picks one.
But all the queries I've tried always return all possible rows.
Here is my most recent attempt:
select *
from EmployeeInfo i
left join EmployeeEmail e ON i.employeeId = e.employeeId
where i.hireDate = 2015
and employeeId IN (
SELECT MIN(employeeId)
FROM EmployeeInfo
GROUP BY employeeId
)
But then again, this returns all possible rows.
Is there a way to get this to work?
Use a sub-query instead of a join:
select *
, (select top 1 E.EmailAddress from EmplyeeEmail E where E.employeeId = I.employeeId)
from EmployeeInfo I
where I.hireDate = 2015;
Note: If you change your mind and decide you do have a preference as to which email address is returned then just add an order by to the sub-query - otherwise it is truly unknown which one you will get.
This should work.
SELECT *
FROM EmployeeInfo
Left JOIN EmployeeEmail
ON EmployeeInfo.employeeId = EmployeeEmail.employeeId
WHERE EmployeeInfo.hireDate = '2015'
GROUP BY EmployeeInfo.employeeId;

SQL - Select highest value when data across 3 tables

I have 3 tables:
Person (with a column PersonKey)
Telephone (with columns Tel_NumberKey, Tel_Number, Tel_NumberType e.g. 1=home, 2=mobile)
xref_Person+Telephone (columns PersonKey, Tel_NumberKey, CreatedDate, ModifiedDate)
I'm looking to get the most recent (e.g. the highest Tel_NumberKey) from the xref_Person+Telephone for each Person and use that Tel_NumberKey to get the actual Tel_Number from the Telephone table.
The problem I am having is that I keep getting duplicates for the same Tel_NumberKey. I also need to be sure I get both the home and mobile from the Telephone table, which I've been looking to do via 2 individual joins for each Tel_NumberType - again getting duplicates.
Been trying the following but to no avail:
-- For HOME
SELECT
p.PersonKey, pn.Phone_Number, pn.Tel_NumberKey
FROM
Persons AS p
INNER JOIN
xref_Person+Telephone AS x ON p.PersonKey = x.PersonKey
INNER JOIN
Telephone AS pn ON x.Tel_NumberKey = pn.Tel_NumberKey
WHERE
pn.Tel_NumberType = 1 -- e.g. Home phone number
AND pn.Tel_NumberKey = (SELECT MAX(pn1.Tel_NumberKey) AS Tel_NumberKey
FROM Person AS p1
INNER JOIN xref_Person+Telephone AS x1 ON p1.PersonKey = x1.PersonKey
INNER JOIN Telephone AS pn1 ON x1.Tel_NumberKey = pn1.Tel_NumberKey
WHERE pn1.Tel_NumberType = 1
AND p1.PersonKey = p.PersonKey
AND pn1.Tel_Number = pn.Tel_Number)
ORDER BY
p.PersonKey
And have been looking over the following links but again keep getting duplicates.
SQL select max(date) and corresponding value
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
SQL Server: SELECT only the rows with MAX(DATE)
Am sure this must be possible but been at this a couple of days and can't believe its that difficult to get the most recent / highest value when referencing 3 tables. Any help greatly appreciated.
select *
from
( SELECT p.PersonKey, pn.Phone_Number, pn.Tel_NumberKey
, row_number() over (partition by p.PersonKey, pn.Phone_Number order by pn.Tel_NumberKey desc) rn
FROM
Persons AS p
INNER JOIN
xref_Person+Telephone AS x ON p.PersonKey = x.PersonKey
INNER JOIN
Telephone AS pn ON x.Tel_NumberKey = pn.Tel_NumberKey
WHERE
pn.Tel_NumberType = 1
) tt
where tt.rn = 1
ORDER BY
tt.PersonKey
you have to use max() function and then you have to order by rownum in descending order like.
select f.empno
from(select max(empno) empno from emp e
group by rownum)f
order by rownum desc
It will give you all employees having highest employee number to lowest employee number. Now implement it with your case then let me know.

SELECT Statement in CASE

Please don't downgrade this as it is bit complex for me to explain. I'm working on data migration so some of the structures look weird because it was designed by someone like that.
For ex, I have a table Person with PersonID and PersonName as columns. I have duplicates in the table.
I have Details table where I have PersonName stored in a column. This PersonName may or may not exist in the Person table. I need to retrieve PersonID from the matching records otherwise put some hardcode value in PersonID.
I can't write below query because PersonName is duplicated in Person Table, this join doubles the rows if there is a matching record due to join.
SELECT d.Fields, PersonID
FROM Details d
JOIN Person p ON d.PersonName = p.PersonName
The below query works but I don't know how to replace "NULL" with some value I want in place of NULL
SELECT d.Fields, (SELECT TOP 1 PersonID FROM Person where PersonName = d.PersonName )
FROM Details d
So, there are some PersonNames in the Details table which are not existent in Person table. How do I write CASE WHEN in this case?
I tried below but it didn't work
SELECT d.Fields,
CASE WHEN (SELECT TOP 1 PersonID
FROM Person
WHERE PersonName = d.PersonName) = null
THEN 123
ELSE (SELECT TOP 1 PersonID
FROM Person
WHERE PersonName = d.PersonName) END Name
FROM Details d
This query is still showing the same output as 2nd query. Please advise me on this. Let me know, if I'm unclear anywhere. Thanks
well.. I figured I can put ISNULL on top of SELECT to make it work.
SELECT d.Fields,
ISNULL(SELECT TOP 1 p.PersonID
FROM Person p where p.PersonName = d.PersonName, 124) id
FROM Details d
A simple left outer join to pull back all persons with an optional match on the details table should work with a case statement to get your desired result.
SELECT
*
FROM
(
SELECT
Instance=ROW_NUMBER() OVER (PARTITION BY PersonName),
PersonID=CASE WHEN d.PersonName IS NULL THEN 'XXXX' ELSE p.PersonID END,
d.Fields
FROM
Person p
LEFT OUTER JOIN Details d on d.PersonName=p.PersonName
)AS X
WHERE
Instance=1
Ooh goody, a chance to use two LEFT JOINs. The first will list the IDs where they exist, and insert a default otherwise; the second will eliminate the duplicates.
SELECT d.Fields, ISNULL(p1.PersonID, 123)
FROM Details d
LEFT JOIN Person p1 ON d.PersonName = p1.PersonName
LEFT JOIN Person p2 ON p2.PersonName = p1.PersonName
AND p2.PersonID < p1.PersonID
WHERE p2.PersonID IS NULL
You could use common table expressions to build up the missing datasets, i.e. your complete Person table, then join that to your Detail table as follows;
declare #n int;
-- set your default PersonID here;
set #n = 123;
-- Make sure previous SQL statement is terminated with semilcolon for with clause to parse successfully.
-- First build our unique list of names from table Detail.
with cteUniqueDetailPerson
(
[PersonName]
)
as
(
select distinct [PersonName]
from [Details]
)
-- Second get unique Person entries and record the most recent PersonID value as the active Person.
, cteUniquePersonPerson
(
[PersonID]
, [PersonName]
)
as
(
select
max([PersonID]) -- if you wanted the original Person record instead of the last, change this to min.
, [PersonName]
from [Person]
group by [PersonName]
)
-- Third join unique datasets to get the PersonID when there is a match, otherwise use our default id #n.
-- NB, this would also include records when a Person exists with no Detail rows (they are filtered out with the final inner join)
, cteSudoPerson
(
[PersonID]
, [PersonName]
)
as
(
select
coalesce(upp.[PersonID],#n) as [PersonID]
coalesce(upp.[PersonName],udp.[PersonName]) as [PersonName]
from cteUniquePersonPerson upp
full outer join cteUniqueDetailPerson udp
on udp.[PersonName] = p.[PersonName]
)
-- Fourth, join detail to the sudo person table that includes either the original ID or our default ID.
select
d.[Fields]
, sp.[PersonID]
from [Details] d
inner join cteSudoPerson sp
on sp.[PersonName] = d.[PersonName];

SQl to select from multiple tables

I have two table emptable1(empid,status) emptable2(empid,week)
i want to select all the empid whose status is 0 in emptable1 and from that list of empid i need to select empid whose week is 7 from the table emptable2
Please help :-)
Not knowing your table structure in detail, but this ought to work:
SELECT
(fields)
FROM
dbo.emptable1 e1
INNER JOIN
dbo.emptable2 e2 ON e1.empid = e2.empid
WHERE
e1.status = 0
AND e2.week = 7
How about using join? Join the two, then do your logic implementation altogether.