SQL query to identify supervisor with employee number and job title - sql-server

I am new to SQL and working on a list to generate employee list with their reporting VPs. the challenge that I have is that not all employees directly reports to VPs, some requires to go through multiple reporting channel to reach VPs.
What I did was creating CTE for each reporting channel and try to join but this method still does not work. For instance, if an employee A reports to supervisor, then supervisor reports to manager, then the manager reports to senior manager, then the senior manager reports to director, and the director reports to VP of their business unit, I need a table lists the information of employee A and the VP responsible for that business unit in following format
Employee number, firstname, lastname, username, jobtitle, VPusername
Below is the script I came up. Would someone please review and let me know what I am doing wrong?
Any help would be appreciated
With Employee
as
(
SELECT [EmployeeNumber]
,[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604]
),
Tier1sup
as
(
SELECT sup1.[EmployeeNumber]
--,emp.[EmployeeNumber]
,sup1.[Username]
,sup1.[JobTitle]
,sup1.[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604] sup1
left join Employee as emp on emp.[SupervisorEmployeeNumber] = sup1.[EmployeeNumber]
where sup1.[JobTitle] like '%VP,%'
),
Tier2sup
as
(
SELECT sup2.[EmployeeNumber]
--,emp.[EmployeeNumber]
,sup2.[Username]
,sup2.[JobTitle]
,sup2.[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604] sup2
left join Tier1sup as tier1 on Tier1.[SupervisorEmployeeNumber] = sup2.[EmployeeNumber]
--left join Employee as emp on emp.[SupervisorEmployeeNumber] = Tier1sup.[SupervisorEmployeeNumber]
where sup2.[JobTitle] like '%VP,%'
),
Tier3sup
as
(
SELECT sup3.[EmployeeNumber]
--,emp.[EmployeeNumber]
,sup3.[Username]
,sup3.[JobTitle]
,sup3.[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604] sup3
left join Tier2sup as tier2 on Tier2.[SupervisorEmployeeNumber] = sup3.[EmployeeNumber]
where sup3.[JobTitle] like '%VP,%'
)
select T1.[EmployeeNumber]
,T1.[FirstName]
,T1.[LastName]
,T1.[Username]
,T1.[JobTitle]
,case
when sup1.[JobTitle] like '%VP,%' then sup1.[Username]
when sup2.[JobTitle] like '%VP,%' then sup2.[Username]
when sup3.[JobTitle] like '%VP,%' then sup2.[Username]
end as SupUser
from [BASE_DB].[dbo].[HR_list_180604] T1
left join Employee as emp on T1.[EmployeeNumber] = emp.[EmployeeNumber]
left join Tier1sup as sup1 on sup1.[EmployeeNumber] = emp.[SupervisorEmployeeNumber]
left join Tier2sup as sup2 on sup2.[EmployeeNumber] = sup1.[SupervisorEmployeeNumber]
left join Tier3sup as sup3 on sup3.[EmployeeNumber] = sup2.[SupervisorEmployeeNumber]

Related

How to cross join tables from multiple servers?

I'm working on a project to create a table that pull information from my local server and 2 online servers. The 2 online servers are both linked with my local server. I only have ability to read from the online servers and the data is to large for me to create a duplicate.
I built some code that would work on Management Studio, however when I place those code into SSRS, I got message that says one of my table already exists. I tried to put a drop table clause in front of that, but then I got message for the next table down the line already existed. And if I pull drop statement for every table, I got a error message for Timeout expired when refresh the fields.
SELECT s.SiteID, s.[StoreName], cf.CustomerID, , cf.AccountNumber, cf.AccountStatus,
cf.Store_ID, cf.InstitutionID, cf.TransactionTime, cf.Comment
INTO #Report_Table1
FROM dbo.View_GetCustomerInfo cf
LEFT JOIN dbo.Store_Table s ON cf.Store_ID = s.Store_ID
;
SELECT t.*, cl.SaleAmount
INTO #Report_Table2
FROM #Report_Table1 t
LEFT JOIN OnlineServe01.Views.dbo.SaleUpdate su
ON t.CustomerID = cl.CustomerID AND t.Store_ID = cl.Store_ID AND [Status] = 'A'
;
SELECT InstitutionID, Source_ID, BankName
INTO #Report_BankName
FROM OnlineServe01.Views.dbo.InstitutionInfo bn
WHERE InstitutionID IN (
SELECT InstitutionID FROM #Report_Table2)
;
SELECT df.*, bn.BankName
INTO #Report_Table3
FROM #Report_Table2 t
LEFT JOIN #Report_BankName bn ON df.InstitutionID = bn.InstitutionID AND df.Store_ID = bn.Store_ID
;
SELECT StoreName, SiteID, CustomerID, SaleAmount
, BankName, AccountNumber, AccountStatus, TransactionTime, Comment
INTO #Report_Table4
FROM #Report_Table3 t
;
SELECT *
INTO #Report_PlayerName
FROM (
SELECT DISTINCT CustomerID, FirstName, LastName,
Dense_Rank () OVER (Partition by CustomerID ORDER BY FirstName) AS Rnk
FROM OnlineServe02.CustomerManagement.dbo.CustomerName
WHERE PreferredName = 0
AND CustomerID IN (SELECT DISTINCT CustomerID FROM #Report_Table4)
) a
WHERE Rnk = 1
;
SELECT t.*, pn.LastName, pn.FirstName, ca.Deposited, ca.Used, ca.InTransit, ca.Available
FROM #Report_Table4 t
LEFT JOIN OnlineServe02.CustomerManagement.dbo.AccountActivity ca
ON t.CustomerID = ca.CustomerID AND t.SiteID = ca.SiteID
LEFT JOIN #Report_PlayerName pn ON t.CustomerID = pn.CustomerID
;

Create and execute stored procedure in SQL Server

I have four tables:
dbo.Projects (id, ProjectName, Areas, PaymentSystem, Districts.id, purpose.id, types.id, etc)
dbo.Districts(id, DistrictsName)
dbo.Purpose (id, PurposeName) - has residential & commercial
dbo.Types (id, typName)
I want to select DistrictsName where PurposeName = 'residential'
I tried this procedure :
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'
this is the result from this procedure:
ID DistrictsName PurposeName
1 District1 residential
2 District1 residential
3 District2 residential
4 District2 residential
i want display the DistrictsName without duplicate or with different values , i a have also one more project per district in projects records . this what i want to display :
ID DistrictsName PurposeName
1 District1 residential
2 District2 residential
how i get this result ,
any help is appreciated.
Why do people use stored procedures when views are much more appropriate? I have never understood this. It seems peculiar to SQL Server users.
In any case, you can do what you want with aggregation:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as id,
d.DistrictName, p.PurposeName
FROM dbo.Projects pr INNER JOIN
dbo.Purpose pu
ON pr.PurposeID = pu.ID INNER JOIN
dbo.Districts d
ON pr.DistrictID = d.ID
WHERE pu.PurposeName = N'Residential'
GROUP BY d.DistrictName, p.PurposeName;
The use of table aliases makes the query much easier to write and to read.
In addition, I don't understand the id column being output. Why would you want to construct a new id? In any case, that is what your data suggests.
Use DISTINCT statement for removing the duplicates:
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT DISTINCT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'

SQL - How to only show the row with the greatest date value based on ID?

I have SQL statements in SQL Server 2008 R2 based on a few joined tables that utilizes all the information I need in my program:
SELECT
Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name,
Loans.Date_Loaned
FROM Users
INNER JOIN Loans ON Users.User_ID = Loans.User_ID
RIGHT OUTER JOIN Laptops ON Loans.Laptop_ID = Laptops.Laptop_ID
This brings up a table similar to:
ID Model_Name ... Name Date_Loaned
1 ... ... Kris 18-08-11
2 ... ... Jo 20-08-11
2 ... ... Bert 18-08-11
4 ... ... Sam 19-08-11
What I'm trying to do is where there would be repeated ID, I want to only show the row with the highest date, like this:
ID Model_Name ... Name Date_Loaned
1 ... ... Kris 18-08-11
2 ... ... Jo 20-08-11
4 ... ... Sam 19-08-11
I'm having problems figuring out how to do this with the SQL statement that I already have. Help!
Use windows functions:
SELECT * FROM(
SELECT Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name,
Loans.Date_Loaned,
row_number()
over(partition by Laptops.Laptop_ID
order by Loans.Date_Loaned desc) rn
FROM Users
INNER JOIN Loans ON Users.User_ID = Loans.User_ID
RIGHT OUTER JOIN Laptops ON Loans.Laptop_ID = Laptops.Laptop_ID) t
WHERE rn = 1
Try this
SELECT Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name,
MAX(Loans.Date_Loaned) AS date
FROM Users
INNER JOIN Loans ON Users.User_ID = Loans.User_ID
RIGHT OUTER JOIN Laptops ON Loans.Laptop_ID = Laptops.Laptop_ID
GROUP BY Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name
Glad you got your answer, but just wanted to mention you might get better performance selecting from Laptops and LEFT OUTER JOIN your Users/Loans sub query. It might be a little easier for the next person to decipher since RIGHT OUT JOIN is not used very often. Using aliases also helps eliminate some typing.
SELECT
l.Laptop_ID,
l.Model_Name,
ul.Name,
ul.Date_Loaned
FROM
Laptops l
LEFT JOIN (
SELECT l.Laptop_ID,
u.Firstname + u.Lastname AS Name,
l.Date_Loaned,
ROW_NUMBER() OVER(PARTITION BY l.Laptop_ID ORDER BY l.Date_Loaned desc) Rn
FROM Loans l
JOIN Users u ON l.User_ID = u.User_ID
) ul ON l.Laptop_ID = ul.Laptop_ID
AND ul.Rn = 1

How can I nest a query as a variable in SQL?

Obviously, SQL isn't my first language, so I need help with something that is probably trivial.
I have the following query:
SELECT Airports.IATA_Code,
COUNT(*) AS Departures,
(SELECT COUNT(*) FROM Flights WHERE DestinationAirportId = 63384) AS Arrivals,
SUM(Flights.Tickets) AS Tickets,
SUM(Flights.Fare * Flights.Tickets) As Revenue,
AVG(Flights.Demand) AS Demand
FROM Flights
LEFT JOIN Airports
ON Flights.OriginAirportId = Airports.Id
WHERE AnalysisId = 2
GROUP BY IATA_Code
ORDER BY Tickets DESC
This query works fine, but I need to replace the hard-coded id of 63384 with the actual Airport Id. This would be Airports.Id but when I try that, I get the following error:
Column 'Airports.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Solved!
Just needed to group by the Airport Id as well:
SELECT Airports.IATA_Code,
COUNT(*) AS Departures,
(SELECT COUNT(*) FROM Flights WHERE DestinationAirportId = Airports.Id) AS Arrivals,
SUM(Flights.Tickets) AS Tickets,
SUM(Flights.Fare * Flights.Tickets) As Revenue,
AVG(Flights.Demand) AS Demand
FROM Flights
LEFT JOIN Airports
ON Flights.OriginAirportId = Airports.Id
WHERE AnalysisId = 2
GROUP BY IATA_Code, Airports.Id <---------------------------
ORDER BY Tickets DESC
Just guessing here... there should be a FK on OriginAirportId referencing Airports.Id. If that's the case, you can do an inner join instead of left join.
Also, try using CROSS APPLY if that's an option for you.
SELECT a.IATA_Code,
COUNT(*) AS Departures,
t.Arrivals,
SUM(f.Tickets) AS Tickets,
SUM(f.Fare * f.Tickets) As Revenue,
AVG(f.Demand) AS Demand
FROM Flights f
INNER JOIN Airports a
ON f.OriginAirportId = a.Id
CROSS APPLY (
SELECT COUNT(*) AS Arrivals
FROM Flights f1
WHERE f1.DestinationAirportId = a.Id) t
WHERE AnalysisId = 2
GROUP BY IATA_Code, a.Id
ORDER BY Tickets DESC
I didn't test this code so please just use it as reference only please.
Or you can even try this...
;WITH AirportDepartureCount AS (
SELECT
OriginAirportId AS AirportId,
Count(*) AS DepartCount,
SUM(f.Tickets) AS Tickets,
SUM(f.Fare * f.Tickets) As Revenue,
AVG(f.Demand) AS Demand
FROM Flights
GROUP BY OriginAirportId
), AirportArrivalCount AS (
SELECT DestinationAirportId AS AirportId, COUNT(*) AS ArrivalCount
FROM Flights
GROUP BY DestinationAirportId
)
SELECT a.Id, a.IATA_Code,
COALESCE(depart.DepartCount,0) AS DepartCount,
COALESCE(arrival.ArrivalCount,0) AS ArrivalCount,
COALESCE(depart.Tickets,0) AS Tickets,
COALESCE(depart.Revenue,0) AS Revenue,
COALESCE(depart.Demand,0) AS Demand
FROM Airports a
LEFT JOIN AirportDepartureCount depart
ON a.Id = depart.AirportId
LEFT JOIN AirportArrivalCount arrival
ON a.Id = arrival.AirportId
ORDER BY COALESCE(depart.Tickets,0) DESC
Main difference here is that this code accounts for all airports (even those that did not have any flights). In your solution, you're ignoring any airports that did not have any departing flights. Perhaps that's by design but thought I'd throw this out there for completeness sake... ;)

SQL statement to select number of tickets opened per user per company

I have these tables: Company, SR_Service (holds ticket information) and Contacts.
I'd like to pull the following for any given month: Company Name, Tickets Opened divided by number of users in each company, Month
e.g.
XYZ Ltd, 0.13, January
ABC Ltd, 0.07, January
DEF Ltd, 0.20, January
etc.
I've been able to get this information for one company by using this query (company_recID is used as the company identifier):
SELECT
co.Company_Name,
(CAST((COUNT(SR_Service_RecID)) AS FLOAT) /
(SELECT count(Contact_RecID)
FROM Contact
WHERE Company_RecID = 2215)) AS 'Tickets Per User'
FROM SR_Service s
LEFT JOIN company as co
on s.company_recid = co.company_recid
LEFT JOIN Contact as con
on co.Company_RecID = con.Contact_RecID
WHERE s.date_entered BETWEEN '2014-12-26 13:36:00' and '2015-01-02 13:36:00'
AND co.Company_RecID = 2215
GROUP BY co.Company_Name
However, I can't seem to get the information in the format as listed in my example above. I really don't want to put a new ID around 250 times!
Thanks in advance
Greg
make it as correlated subquery
SELECT co.Company_Name,
( Cast(( Count(SR_Service_RecID) ) AS FLOAT) / (SELECT Count(Contact_RecID)
FROM Contact cc
WHERE cc.Company_RecID = co.Company_RecID) ) AS 'Tickets Per User',
Datename(mm, date_entered) [month]
FROM SR_Service s
LEFT JOIN company AS co
ON s.company_recid = co.company_recid
LEFT JOIN Contact AS con
ON co.Company_RecID = con.Contact_RecID
WHERE s.date_entered BETWEEN '2014-12-26 13:36:00' AND '2015-01-02 13:36:00'
GROUP BY co.Company_Name,
Datename(mm, date_entered)

Resources