Select unique random posting/recruitment places of employees within a list of places - sql

I am trying to select unique random posting/recruitment places of employees within a list of places, all the employees are already posted at the places, i am trying to generate a new random posting place for them with "where" condition that "employee new random location will not be equal to their home place"
Employee table is :
EmpNo Empname CurrentPosting Home Designation RandomPosting
1 Satish Kumar Samastipur Gazi Manager
2 Anil Kumar Singh Vaishali Patna Manager
3 Rajdev Prasad Nawada Gaya PO
4 Rajesh Kumar Sheikhpura Muzaffarpur PO
5 Jitendra Kumar Banka Bhagalpur Clerk
And so on...
And Places table is
PlaceID PlaceName Manager PO Clerk
1 Araria 2 0 1
2 Arwal 1 1 1
3 Aurangabad 1 0 2
4 Banka 2 1 1
5 Begusarai 1 1 1
6 Bhagalpur 1 1 2
7 Bhojpur 0 2 0
and so on...
i tried with rand() and newid() like as below,
select Employee.*, Place.PlaceName As RandomPosting from Employee
inner join Place on Place.PlaceID=Employee.EmpNo order by newid()
But unable to select what is required... that is to assign each Employee a PlaceName(from Place) randomly which is not equal to CurrentPosting and Home(in Employee).
Thanks in advance.

WITH cteCrossJoin AS (
SELECT e.*, p.PlaceName,
ROW_NUMBER() OVER(PARTITION BY e.EmpNo ORDER BY NEWID()) AS RowNum
FROM Employee e
CROSS JOIN Place p
WHERE e.Home <> p.PlaceName
)
SELECT *
FROM cteCrossJoin
WHERE RowNum = 1;

Related

List records from a chosen employee to the ultimate manager

Given the following Table (In Postgres):
EmployeeID
EmployeeName
ManagerID
1
David
NULL
2
Jessica
NULL
3
Gregg
1
4
Joe
3
5
Brandon
NULL
6
Leslie
4
7
Harry
6
8
Paul
NULL
9
Frank
5
Starting from Employee ID 7 (Harry) - how do I list only the records, bottom-up, in the hierarchy until I get to the ultimate manager (which should be David, in this case)? Should I use recursive CTE? If so, how does that query look?
Expected Output:
EmployeeID
EmployeeName
ManagerID
1
David
NULL
3
Gregg
1
4
Joe
3
6
Leslie
4
7
Harry
6
In the common table expression, you can recognize:
the base step, where you select the record relatively to employee no 7
the recursive step, where you match managers with currently retrieved employees.
The recursion stops when the INNER JOIN does not return any more extra record.
WITH RECURSIVE cte AS (
SELECT * FROM tab WHERE EmployeeID = 7
UNION ALL
SELECT mgr.*
FROM cte emp
INNER JOIN tab mgr
ON emp.ManagerID = mgr.EmployeeID
)
SELECT *
FROM cte
Check the demo here.

Displaying columns as rows SQL

I have the below tables:
Corporate table:
CorporateId DirectorId ManagerId SalesId
1 1 1 1
2 2 2 3
3 3 4 5
Employee table:
EmployeeId FirstName LastName
1 Tim Sarah
2 Tom Paulsen
3 Tam Margo
4 Eli Lot
5 Ziva Lit
I want to display, for one corporate,the names of the Director, Manager and Sales in rows. Example with corporate 3:
EmployeeId FirstName LastName
3 Tam Margo
4 Eli Lot
5 Ziva Lit
How can I do that? I know how to display rows as columns using pivot, but unsure if pivot can be used here also.
Any help please?
You may join the two tables as the following:
SELECT E.EmployeeId, E.FirstName, E.LastName
FROM Employee E JOIN Corporate C
ON E.EmployeeID IN (C.DirectorId ,C.ManagerId ,C.SalesId)
WHERE C.CorporateId=3
See a demo.
You can first un-pivot your rows into columns by using cross apply, after which you simply join the pivoted rows to your employee table:
select e.*
from corporate c
cross apply (
select EmployeeId from (
values (Directorid), (ManagerId), (SalesId)
)r(EmployeeId)
)r
join employee e on e.EmployeeId = r.EmployeeId
where c.CorporateId = 3;

parent details in same row conditionally

I have a table Called EmployeeLevel
Id Position ShouldApproveLeave
1000 1 0
2000 2 1
3000 3 0
4000 4 0
Note that the bool column ShouldApproveLeave is true for only one row
I have a table Employee with the following structure with LevelId as foreign key to EmployeeLevel
Id ParentId Name LevelId
1000 NULL Jack 1000
2000 1000 John 2000
3000 2000 Nick 3000
4000 3000 James 4000
I need a query to get employee details, position details as well as the manager responsible for his leave approval as below
query (id = 4000)
Id Name LevelPosition LeaveApprovalLevel LeaveApprovingManager
4000 James 4 2 John
query (id = 3000)
Id Name LevelPosition LeaveApprovalLevel LeaveApprovingManager
3000 Nick 3 2 John
query (id = 2000)
Id Name LevelPosition LeaveApprovalLevel LeaveApprovingManager
2000 John 2 2 John
Also I want to check leave approving manager only upwards in the hierarchy.
query (id = 1000)
Id Name LevelPosition LeaveApprovalLevel LeaveApprovingManager
1000 Jack 1 2 NULL
I wrote a CTE to get the manager with LeaveApproving bit set. Getting the employee with level is also straightforward. My issue is to get all these details in the same row.
So the question really is I got individual results for employee details and Leave Approving manager. How can I get this in a single row?
I managed to get individual queries for the following
employee details
Id ParentId Name Position
4000 3000 James 4
LeaveApprovalLevel details
Level
2
LeaveApprovingManager details
Id ParentId Name
2000 1000 John
How can I join these so that I will get this?
Id Name LevelPosition LeaveApprovalLevel LeaveApprovingManager
4000 James 4 2 John
Any tips are appreciated.
Here is one approach:
Get the hierarchy for the employee.
Use joins to get the information on the flag you want.
Use joins to bring back all the information you want.
As a query:
with cte as (
select e.id, e.parentid, 1 as lev
from employee e
where id = 4000
union all
select cte.id, e.parentid, lev + 1
from cte join
employee e
on e.id = cte.parentid
)
select e.*, el.*
from cte join
employee e
on cte.id = e.id join
employee el
on cte.parentid = el.id join
EmployeeLevel eml
on cte.parentid = eml.id;
try this
SELECT e1.Id, e1.Name, el1.Position as LevelPosition, el2.Position as LeaveApprovalLevel, e2.Name as LeaveApprovingManager FROM Employee e1 INNER JOIN EmployeeLevel el1 ON e1.LevelId = el1.Id LEFT JOIN Employee e2 ON e1.ParentId = e2.Id LEFT JOIN EmployeeLevel el2 ON e2.LevelId = el2.Id;
Here is the response
Check, here is the working Fiddle

T-SQL - Concatenate Multiple Rows

I am struggling with a query to return a list of managers with their respective employees
I have three tables as follows:
Managers
ManagerID ManagerName
1 Bob
2 Sally
3 Peter
4 George
EmployeeManager
EmployeeID ManagerID
1 1
1 1
2 2
2 2
3 3
3 3
4 4
4 4
Employees
EmployeeID EmployeeName
1 David
1 Joseph
2 Adam
2 Pete
3 Mark
3 Mavis
4 Susan
4 Jennifer
Desired Result Set
ManagerName CountEmployee Employees
Bob 2 David, Joseph
Sally 2 Anish, Pete
Peter 2 Mark, Mavis
George 2 Susan, Jennifer
The query I am currently using is as follows:
Select m.ManagerName
,Count(e.EmployeeName) Over(Partition By m.ManagerID) as CountEmployee
,Rank() Over(Partition By m.ManagerID Order By em.EmployeeID) [RankEmployee]
,e.EmployeeName
From dbo.Employees e
Left Join dbo.EmployeeManager em on em.ManagerID=e.ManagerID
Left Join dbo.Managers m on m.ManagerID=em.ManagerID;
This returns a list of managers and employees on individual rows but I'm struggling to concatenate the employee names as per the above table.
Any ideas or solutions?
Manpaal Singh
You can stuff the result to comma seperated result.
Select m.ManagerName
,Count(e.EmployeeName) Over(Partition By m.ManagerID) as CountEmployee
,Rank() Over(Partition By m.ManagerID Order By em.EmployeeID) [RankEmployee]
,STUFF((SELECT ',' + e.EmployeeName
FOR XML PATH('')), 1, 1, '') AS EmployeeName
From dbo.Employees e
Left Join dbo.EmployeeManager em on em.ManagerID=e.ManagerID
Left Join dbo.Managers m on m.ManagerID=em.ManagerID
SELECT M.ManagerName, E.EmployeeName
FROM Managers AS M
INNER JOIN EmployeeManager AS EM ON M.ManagerID = EM.ManagerID
INNER JOIN Employees AS E ON EM.EmployeeID = E.EmployeeID
ORDER BY M.ManagerName
This will give a list of managers and their employees.
when you fix the ID's of the employees table.
1 David
1 Joseph
2 Adam
2 Pete
3 Mark
3 Mavis
4 Susan
4 Jennifer
should be:
1 David
2 Joseph
3 Adam
4 Pete
5 Mark
6 Mavis
7 Susan
8 Jennifer
you can use recursive sql to convert rows in a string :
with t1 (mngId, empName) as (
select a.mngId,
b.empname
from manager as a, employee as b
where b.mngId = a.mngId),
t2 (mngID, nbr, empName, all_name) as (
select mngId,
cast(1 as Int),
min(empName),
cast(min(empName) as varchar(1000)
from t1
group by mngId
union all
select b.mngId,
b.nbr+1,
a.empName,
trim(b.all_name) concat ', ' concat a.empName
from t0 as a, t1 as b
where b.mngId = a.mngId
and a.empName > b.empName
and a.empName = (
select min( c.empName)
from t0 as c
where c.mngId = b.mngId
and c.empName > b.empName )
)
select *
from t1 as e
where nbr = (
select max(nbr)
from t1 as d
where d.mngId = e.mngId )

SQL Server basics - where clause

This is the code I have:
use TSQL2012
select
emp.empid, emp.firstname, emp.mgrid,
manager.firstname as manager_name,
sum(unique(emp.mgrid)) as Total
from
HR.Employees AS emp, HR.Employees as manager
where
emp.mgrid = manager.empid
go
And the result I am supposed to get is:
empid firstame mgrid manager_name Total
1 2 Don 1 Sara 1
2 3 Judy 2 Don 2
3 4 Yael 3 Judy 2
4 5 Sven 2 Don 2
5 6 Paul 5 Sven
6 7 Russell 5 Sven
7 8 Maria 3 Judy
8 9 Zoya 5 Sven
I can't get the last column (Total). Any help would be appreciated
One way of doing it is by the use of CROSS APPLY:
select emp.empid, emp.firstname, emp.mgrid, manager.firstname as manager_name,
x.cnt as Total
from Employees AS emp
inner join Employees as manager on emp.mgrid = manager.empid
cross apply (
select count(*)
from Employees AS e
where e.mgrid = emp.mgrid) AS x(cnt)
Demo here
Edit:
You can also use a CTE in this way:
;With C as (
select b.mgrid, count(*) as Total
from Employees as b
group by mgrid
)
select emp.empid, emp.firstname, emp.mgrid, manager.firstname as manager_name,
Total
from Employees AS emp
inner join Employees as manager on emp.mgrid = manager.empid
inner join C on emp.mgrid = C.mgrid
Demo here