SQL Select employees with work history in multiple states - sql

I need a query that will show only employees who have been paid in more than one state.
The query will pull three columns:
EmployeeID
WorkLocation
LastPayDate
My current, unsuccessful attempt:
Select EmployeeID
, WorkLocation
, max(LastPayDate)
from Table
group by EmployeeID, WorkLocation
having COUNT(distinct WorkLocation) > 1
This query pulls zero records. I know there are employees who have worked in multiple states, however. I am not sure where my logic breaks down.
Any instruction is much appreciated.

You need to have a count(workLocation) > 1 which indicates that they have worked in more than 1 state. Specify this in the HAVING clause. Since you're only concerned in GROUPS which contain multiple WorkLocations.
If you're trying to check for multiple work locations within a specific year, you will perform that logic in the WHERE clause.
select EmployeeId
from table xyz
//where year(LastPayDate) == 2015
group by EmployeeId
having count(distinct WorkLocation) > 1

Figured it out. I needed to use a subquery. Solution as follows:
Select t.EmployeeID
, t.WorkLocation
, t.LastPayDate
From Table t
Where t.EmployeeID in
(
Select t2.EmployeeID
From Table t2
Group by t2.EmployeeID
Having count(distinct t2.WorkLocation) > 1
)
Group by t.EmployeeID, t.WorkLocation
Order by t.EmployeeID
Thanks to everyone for helping.

Related

Use SQL to exclude rows with no change in specific column from query

How can I exclude the yellow highlighted rows? The requirement of the query is to return only rows where the job title changed, but the raw data includes extraneous rows with different effective dates which we want to be able to automatically exclude with SQL.
This is because the source system has a record effective date column that is common to several columns. We cannot change this architecture and so need the ability to exclude records from the output.
Edit to include error image from suggested answer:
select
a.*
FROM
jobtitles a
LEFT JOIN jobtitles b
ON a.id = b.id AND
a.effdate < b.effdate
WHERE b.id IS NULL
something like that, that would get the latest job title anyway
you might be able to use that "pseudo table" to further query
on considering your question further, how about
select
MIN(effdate) as effdate, jobtitle
FROM jobtitles
group by employeeid, jobtitle
(I'm making the assumption they don't change job titles back and forth, if so you're basically screwed, so be aware of that)
If JobTitle of an employee does not reverted to previous job titles, use the following query:
SELECT EmployeeID,
Name,
JobTitle,
MAX(Name) AS Name,
MIN(EffectiveDate) AS EffectiveDate
FROM jobtitles
GROUP BY EmployeeID, JobTitle
ORDER BY EmployeeID ASC, EffectiveDate DESC
If JobTitle of employees can be reverted/change to title that they have already obtained in the past, use the following query:
Edit: Update query according to table schema provided in question
SELECT ASSOCIATE_ID,
JOB_TITLE_DESCRIPTION,
POSITION_EFFECTIVE_DATE
FROM (
SELECT
ASSOCIATE_ID,
JOB_TITLE_DESCRIPTION,
JOB_TITLE_CODE,
POSITION_EFFECTIVE_DATE,
LEAD(JOB_TITLE_CODE,1, '0') OVER (ORDER BY ASSOCIATE_ID ASC, POSITION_EFFECTIVE_DATE DESC) AS PREV_TITLE_ID
FROM EMP_JOB_HISTORY
) AS tmp
WHERE tmp.PREV_TITLE_ID <> tmp.JOB_TITLE_CODE

SQL How many of a counted row is in another counted row?

I've been stuck on how to write a particular query for the following question:
How many employees are in how many businesses?
My end result should look like this:
EmployeeId Count
BusinessId Count
1
23473423
2
56245764
3
834456
So there are 23473423 businesses that have 1 employee, 23473423 businesses that have 2 employees, etc.
I have a table with a list of items including EmployeeId and BusinessId. A BusinessId can connect to many EmployeeIds.
So far I have the following code to get me employees per business
Select BusinessId,
Count(EmployeeId) as EIdCount
From Table
Group by BusinessId
Which gets me me a list of BusinessIds and how many EmployeeIds are attached to it.
BusinessId
EIdCount
23
2
24
5
25
1
26
3
But now I need to figure out how to further group it to where the BusinessId's can be grouped by the Grouped Counted Employee Ids. I've looked at subqueries, having by, and group but I am still at a loss how to progress this without running into an error.
Thank you for your help in advance!
Not sure if this is what you want:
Select EIdCount, Count(BusinessId)
From (
Select BusinessId,
Count(EmployeeId) As EIdCount
From Table
Group by BusinessId
) A
Group By EIdCount
Just use a subquery:
select
EIdCount,count(BusinessId) as [BusinessId Count]
from
(
--your original query/start
Select BusinessId,
Count(EmployeeId) as EIdCount
From Table
Group by BusinessId
--your original query/end
)t
group by EIdCount

How do I ensure that the Number column has values greater than one?

I have tried adding "HAVING Number>1" However this doesn't work correctly it only outputs 1 row
SELECT
T.EmployeeID,
COUNT(*) AS "Number"
FROM (
SELECT
Skill.Title,
Skill.SkillID,
EmployeeSkill.EmployeeID
FROM Skill
RIGHT JOIN EmployeeSkill ON EmployeeSkill.SkillID = Skill.SkillID
) T
GROUP BY T.EmployeeID
I believe it should work if you will use "having count(*)>1" instead of "having number>1"
If you want from the query only the rows where Number > 1
then you need to add a HAVING clause to the statement:
HAVING COUNT(*) > 1
I suspect that you are looking to pull out employees that have at least two skills. If so, it looks like that's a simple aggregate query on table EmployeeSkill, like:
SELECT EmployeeID, COUNT(*)
FROM EmployeeSkill
GROUP BY EmployeeID
HAVING COUNT(*) > 1

Table inner join itself

I have a table with 3 columns (code, state, date), it records the history of a code state, each code may have changed state multiple times.
I want to show the last state of each code what I did was like this
SELECT code,MAX(date), ....
FROM table
GROUP BY code.
I don't know what to put exactly to get the state. I tried to just put state so it gets the state corresponding to the combination of code,max(date) but it gives me the error of not in aggregate function.
thank you in advance for your help.
If I understand you have data such as
CODE State Date
1 IL 1/1/2016
1 IA 1/1/2017
1 AL 1/1/2015
and you want to see in your results
1 IA 1/1/2017
using a window function and a common table expression (with): we assign a row number to each code based on the date in descending order and return only the first row for each.
With CTE AS (SELECT code
, date
, state
, Row_number() over (partition by code order by date desc) RN
FROM table )
SELECT Code, Date, State
FROM CTE
WHERE RN =1
Using a subquery: (we get the max date for each code and then join back to the base set to limit the rows returned.
SELECT A.code, A.date, A.state
FROM table A
INNER JOIN (SELECT max(date) mdate, code
FROM table
GROUP BY code) B
on A.Code = B.Code
and A.Date = B.MDate
The later query was used when/if window functions are not available. The modern method of solving your question is using the first approach.
In essence what the 1st query does is assign the # 1 to x for each code based on the date descending. So the max date gets a RN of 1 for each code. Thus when we say where RN = 1 we only return codes/states/records having max dates for the code in question. We use a with statement because we need the RN to materialize (actually get generated in memory) so that we can then limit by it in the second part of the with (common table expression) query.
If you're doing an aggregate, like MAX(), then all other non-aggregate columns that are in your select, need to also be in your GROUP BY. That's why you're getting the error when you add state to only the select. If you add it to the select and group by it, you'll get your results:
SELECT State, Code, MAX(Date)
FROM table
GROUP BY State, Code
If you want to user inner join like you mention in your post Inner join back to itself with matching code and date
SELECT *
FROM table t1
INNER JOIN (SELECT code,MAX(date)
FROM table
GROUP BY code) codeWithLatestDate ON t1.code = codeWithLatestDate.code AND t1.date = codeWithLatestDate.dat3
However I would suggest add state to your GROUP BY clause and SELECT cluase
SELECT code,MAX(date),state
FROM table
GROUP BY code, state
Youn can do it with a join to itself
SELECT State,Code,Date
FROM table t
JOIN (
SELECT Code, MAX(Date) as Date
FROM table
GROUP BY Code) t1 on t1.Code= t.Code and t.Date=t1.Date

Using Aggregate Functions in sql

Hoe can I do following thing without using a VIEW from one Query.
!--CREATE THE VIEW
CREATE OR REPLACE VIEW BDGTMGR
AS
SELECT MANAGERID,SUM(BUDGET) AS BDGT FROM
N_DEPT GROUP BY MANAGERID ;
!-- THEN GET RESULT FROM THE VIEW
SELECT MANAGERID FROM BDGTMGR WHERE BDGT = (select MAX(BDGT) FROM BDGTMGR);
Here N_DEPT is may original Table which has columns named DID, MANAGERID and BUDGET.
I want to get MANAGERID who controls Maximum Budget. A Manager can control more than one Department. DID is the primary key for this table.
How can I do this?
select MANAGERID,SUM(BDGT)
from N_DEPT
group by MANAGERID
order by SUM(BDGT) desc limit 1
You can do it like this:
SELECT aux.MANAGERID
FROM
(SELECT MANAGERID,
SUM(BUDGET) AS BDGT
FROM N_DEPT
GROUP BY MANAGERID) aux
INNER JOIN BDGTMGR b ON b.MANAGERID = aux.MANAGERID
WHERE b.BDGT = (select MAX(BDGT) FROM BDGTMGR);
The following query will work (modify depending on your flavour of SQL):
SELECT TOP 1 MANAGERID FROM N_DEPT GROUP BY MANAGERID ORDER BY SUM(BUDGET) DESC