single row based on min of one column with a join - sql

I am trying to get the certain columns from a row associated with min(date) by joining with another table.
I am using this in Hive.
My query is:
With temp1 as
(Select employee_id as emp_id, min(date) as min_date from employee where employee_id in (select employee_id from employee_sal) group by employee_id)
Select
employee_sal.dept_code,
Temp1.emp_id,
employee_sal.dept_name,
employee_sal.paid_loc,
employee_sal.country_paid,
min_date
from employee_sal inner join temp1 on employee_sal.employee_id = emp1.employee_id
But I need the dept_name, paid_loc, country_paid based on the min(date) based on employee table like this:
employee_sal.dept_code, Temp1.emp_id, temp1.dept_name, temp1.paid_loc, temp1.country_paid, min_date
These should be the values associated with the min(date) from employee.

With temp1 as
(Select employee_id as emp_id, min(date) as min_date from employee where employee_id in (select employee_id from employee_sal) group by employee_id)
Select
employee_sal.dept_code,
Temp1.emp_id,
employee_sal.dept_name,
employee_sal.paid_loc,
employee_sal.country_paid,
min_date
from employee_sal inner join temp1 on employee_sal.employee_id = emp1.employee_id And employee_sal.min_date = emp1.min_date

Related

How do I get the first and last 10 records in a table?

I need to find 10 employees with the largest difference between current salary and salary, when they were hired and 10 with the smallest difference.
The table looks like this salary table and contains 2844047 records.
My code is:
WITH t1 AS (
SELECT emp_no, FIRST_VALUE(salary) OVER (PARTITION BY emp_no ORDER BY from_date) AS `first`
FROM salaries),
t2 AS (
SELECT emp_no, salary AS last
FROM salaries
WHERE to_date = '9999-01-01')
(SELECT DISTINCT emp_no, last - first AS `diff`
FROM t1
INNER JOIN t2 USING (emp_no)
ORDER BY `diff`
LIMIT 10)
UNION ALL
(SELECT DISTINCT emp_no, last - first AS `diff`
FROM t1
INNER JOIN t2 USING (emp_no)
ORDER BY `diff` DESC
LIMIT 10);
but it takes a lot of time to execute this.
Condition where to_date = '9999-01-01' means that employee is still working.
How can I optimize this query, so it will execute faster?
The join is not necessary. Perhaps this will be a bit faster:
SELECT s.*
FROM (SELECT s.*,
ROW_NUMBER() OVER (ORDER BY salary - first ASC) as seqnum,
ROW_NUMBER() OVER (ORDER BY salary - first DESC) as seqnum_desc
FROM (SELECT s.*,
FIRST_VALUE(salary) OVER (PARTITION BY emp_no ORDER BY from_date) AS first
FROM salaries s
) s
WHERE to_date = '9999-01-01'
) s
WHERE seqnum_asc <= 10 or seqnum_desc <= 10;

SQL Server Group Records Based Another Columns

I am working on a table that contains employee data. The table has historical employee records based on department and year as follows:
Now I want to consolidate records based on EmployeeId, Department and get the Min FromYear and Max ToYear like this:
I tried to use a query :
Select EmployeeId, Department, MIN(FromYear), MAX(ToYear)
from Employee
GROUP BY EmployeeId, Department
But this query fails for the employee with ID 3 as it returns me only 2 rows:
I have added a similar structure and query here: http://sqlfiddle.com/#!9/6f1e53/5
Any help would be highly appreciated!
This is a gaps-and-islands problem. Identify the islands using lag() and a cumulative sum. Then aggregate:
select employeeid, department, min(fromyear), max(toyear)
from (select e.*,
sum(case when prev_toyear >= fromyear - 1 then 0 else 1 end) over (partition by employeeid order by fromyear) as grp
from (select e.*,
lag(toyear) over (partition by employeeid, department order by fromyear) as prev_toyear
from employee e
) e
) e
group by employeeid, department, grp
order by employeeid, min(fromyear);
Here is a db<>fiddle.
you can use self join as well
select a.employeeid, min(a.fromyear), max(b.toyear) from emp a
inner join emp b on a.employeeid=b.employeeid
group by a.employeeid

How to fetch rows with MAX condition involving multiple columns

I have an Employee table with the following columns:
Emp_Id
Emp_Name
ProjectName
ProjectStartDate
ProjectEndDate
Emp_ManagerId
Every employee can work in multiple projects at the same time.
I want the fetch all the records in the table for each employee with max ProjectStartDate. If an employee has multiple records with same ProjectStartDate then the record with max ProjectEndDate should be returned.
All dates in MM/DD/YYYY
You can use ROW_NUMBER() in a subquery to rank the records of each employee by descending project start and end date, and then filter on the top record of each employee in the outer query:
SELECT *
FROM (
SELECT
e.*,
ROW_NUMBER() OVER(PARTITION BY Emp_Id ORDER BY ProjectStartDate DESC, ProjectEndDate DESC) rn
FROM Employee e
) x
WHERE rn = 1
You can use the ROW_NUMBER() function, as in:
select *
from (
select
*,
row_number() over(partition by emp_id
order by projectstartdate desc, projectenddate desc) as rn
from employee
) x
where rn = 1

How to find duplicate record for same date

I have a room inventory table each room has one record for each day,
but some rooms have double record for a day. I want to query to pull out those id.
Inventory_table => id, roomid, inv_date....
The following may get you a list of the rooms with duplicates.
select id, roomid, inv_date, count(room)
from room_inventory
group by id, roomid, inv_date
having count(room) > 1;
Select Id, count(*) from inventory_table group by roomid, inv_date having count(*)>1
select empno,count() from emp group by empno having count()>1;
its with reapted values
select * from emp where rowid not iN(select min(rowid) from emp group by deptno)

SQL Syntax on DISTINCT Query

I have an Employee Table with their DeptCode. I want list of distinct DeptCode and their first created date in the Employee Table. This will also tell which employee was first entered for a specific dept in the Employee Table.
I used:
SELECT DISTINCT DEPTCODE,
CREATEDDATE
FROM EMPLOYEE
The Date Return is incorrect.
Any specific syntax to handle this issue.
Try:
SELECT DEPTCODE,
Min(CREATEDDATE)
FROM EMPLOYEE
GROUP BY DEPTCODE
If you want the department codes, earliest creation date, and the name of the employee, then I would recommend window functions:
select deptcode, name, createddate
from (select e.*,
row_number() over (partition by deptcode order by createddate) as seqnum
from employee e
) e
where seqnum = 1;
You can use GROUP BY and MIN to achieve this.
SELECT DEPTCODE, MIN(CREATEDDATE)
from EMPLOYEE
GROUP BY DEPTCODE
Something like this.
SELECT deptcode,
employee_name,
minddate
FROM employee
JOIN (SELECT deptcode,
Min(createddate) mindate
FROM employee
GROUP BY deptcode) temp
ON employee.deptcode = temp.deptcode
AND createddate = mindate