need employee details who has only one employment - sql

need employee details who has only one employment
for example this is the table
ID Name StartDate EndDate
1 Fischel 01-May-97 Jan-99
1 Fischel 08-May-92 02-Feb-99
1 Fischel 11-May-92 04-May-10
2 David 10-aug-1980 05-May-1981
3 John 12-sep-1988 06-June-2009
3 John 23-Aug-92 01-Nov-11
Output like this
2 David 10-aug-1980 05-May-1981

Select * from
(select *,row_number() over (partition by id order by StartDate desc ) as rnm
from your table
)Derived_Table
where Derived_Table.rnm=1;
OR
select * from table where id in (
select id
from table group by id having count(*) =1) z;

Use NOT EXISTS to return a user if same user-name doesn't have any other dates.
select ID, Name, StartDate, EndDate
from tablename t1
where not exists (select 1 from tablename t2
where t2.id = t1.id
and (t2.StartDate <> t1.StartDate
or t2.EndDate <> t1.EndDate))
Or, have a sub-query that return all id only appearing once:
select ID, Name, StartDate, EndDate
from tablename t1
where id in (select id from tablename
group by id
having count(*) = 1)

Related

get records that have only 1 record per group

we have attendance db data as follows (sql server)
empid date type
1 01-Jan In
1 01-Jan Out
2 01-Jan In
3 01-Jan In
3 01-Jan Out
How can we get records that have only 1 record per date per employee (in above case empid 2 for 01-jan)?
The query should simply list all records of employees that have only single type for a day.
EDIT
The result set should be a bit more specific: show all employee who only have "In" for a date but no "Out"
Use Having
select empid, date, count(*)
from Mytable
group by empid, date
having count(*) = 1
You can use this to get the full line:
select t1.*
from MyTable t1
inner join
(
select empid, date, count(*)
from Mytable
group by empid, date
having count(*) = 1
) t2
on t1.empid = t2.empid
and t1.date = t2.date
You can use window functions:
select t.*
from (select t.*,
count(*) over (partition by empid, date) as cnt
from t
) t
where cnt = 1;
You can also use aggregation:
select empid, date, max(type) as type
from t
group by empid, date
having count(*) = 1;
Use a correlated subquery
select * from tablename a
where not exists (select 1 from tablename b where a.empid=b.empid and a.date=b.date and type='Out')
OR
select empid, date,count(distinct type)
from tablename
group by empid,date
having count(distinct type)=1
The Solution is Very Simple, You can use 'DISTINCT' function.
Query Should be as,
SELECT DISTINCT empid FROM attendance
This will return only 1 record per date per employee.
For Your Reference, Check it out- https://www.techonthenet.com/sql_server/distinct.php
This will work if we have ID with 1 IN OR 1 OUT as well
Declare #t table (empid int,date varchar(50),types varchar(50))
insert into #t values (1,'01-Jan','IN')
insert into #t values (1,'01-Jan','OUT')
insert into #t values (2,'01-Jan','IN')
insert into #t values (3,'01-Jan','OUT')
insert into #t values (4,'01-Jan','OUT')
select * from #t a
where not exists (select 1 from #t b where a.empid=b.empid and a.types!=b.types)

SQL(Need to print all the duplicate value IDs)

Empid----Name
1 aa
2 bb
3 cc
4 aa
5 bb
I need to get output to print EmpId number for which names are repeated
output Required:
1,2,4,5.
If you are using sql server,use the below script.
;WITH CTE_1 AS
(
SELECT *,COUNT(1)OVER(PARTITION BY Name ORDER BY Name) CNT
FROM [YourTable]
)
SELECT ID
FROM [CTE_1]
WHERE CNT > 1
Try this
select empid from table
where name in (select name from table group by name having count(*)>1)
SELECT *
FROM table AS parent
WHERE EXISTS(
SELECT *
FROM table AS sub
WHERE sub.Name == parent.Name && parent.Empid <> sub.Empid
)
Try this.
select distinct t.Empid from
#Your_Table t inner join
(
select Name, COUNT (Name) as count
from #Your_Table
group by Name
having COUNT (Name) > 1
)a on a.Name=t.Name
order by t.Empid
SELECT * FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Name) RowNo,*
From Your_Table
) a
WHERE RowNo > 1

SQL - How to Order By in UNION query

Is there a way to union two tables, but keep the rows from the first table appearing first in the result set? However orderby column is not in select query
For example:
Table 1
name surname
-------------------
John Doe
Bob Marley
Ras Tafari
Table 2
name surname
------------------
Lucky Dube
Abby Arnold
Result
Expected Result:
name surname
-------------------
John Doe
Bob Marley
Ras Tafari
Lucky Dube
Abby Arnold
I am bringing Data by following query
SELECT name,surname FROM TABLE 1 ORDER BY ID
UNION
SELECT name,surname FROM TABLE 2
The above query is not keeping track of order by after union.
P.S - I dont want to show ID in my select query
I am getting ORDER BY Column by joining tables. Following is my real query
SELECT tbl_Event_Type_Sort_Orders.Appraisal_Event_Type_ID AS Appraisal_Event_Type_ID , ISNULL(tbl_Appraisal_Event_Types.Appraisal_Event_Type_Display_Name, 'UnCategorized') AS Appraisal_Event_Type_Display_Name
INTO #temptbl
FROM tbl_Event_Type_Sort_Orders
INNER JOIN tbl_Appraisal_Event_Types
ON tbl_Event_Type_Sort_Orders.Appraisal_Event_Type_ID = tbl_Appraisal_Event_Types.Appraisal_Event_Type_ID
WHERE 1=1
AND User_Name='abc'
ORDER BY tbl_Event_Type_Sort_Orders.Sort_Order
SELECT * FROM #temptbl
UNION
SELECT DISTINCT (tbl_Appraisal_Event_Types.Appraisal_Event_Type_ID) AS Appraisal_Event_Type_ID , ISNULL(tbl_Appraisal_Event_Types.Appraisal_Event_Type_Display_Name, 'UnCategorized') AS Appraisal_Event_Type_Display_Name
FROM tbl_Appraisal_Event_Types
INNER JOIN tbl_Appraisal_Events
ON tbl_Appraisal_Event_Types.Appraisal_Event_Type_ID = tbl_Appraisal_Events.Event_Type_ID
INNER JOIN tbl_Appraisals
ON tbl_Appraisal_Events.Appraisal_ID = tbl_Appraisal_Events.Appraisal_ID
WHERE 1=1
AND ((tbl_Appraisals.Assigned_To_Staff_User) = 'abc' OR (tbl_Appraisals.Assigned_To_Staff_User2) = 'abc' OR (tbl_Appraisals.Assigned_To_Staff_User3) = 'abc')
Put a UNION ALL in a derived table. To keep duplicate elimination, do select distinct and also add a NOT EXISTS to second select to avoid returning same person twice if found in both tables:
select name, surname
from
(
select distinct name, surname, 1 as tno
from table1
union all
select distinct name, surname, 2 as tno
from table2 t2
where not exists (select * from table1 t1
where t2.name = t1.name
and t2.surname = t1.surname)
) dt
order by tno, surname, name
You can use a column for the table and one for the ID to order by:
SELECT x.name, x.surname FROM (
SELECT ID, TableID = 1, name, surname
FROM table1
UNION ALL
SELECT ID = -1, TableID = 2, name, surname
FROM table2
) x
ORDER BY x.TableID, x.ID
You can write as below, if you are ok with duplicate data then please use UNION ALL it will be faster:
SELECT NAME, surname FROM (
SELECT ID,name,surname FROM TABLE 1
UNION
SELECT ID,name,surname FROM TABLE 2 ) t ORDER BY ID
this will order the first row sets first then by anything you need
(haven't tested the code)
;with cte_1
as
(SELECT ID,name,surname,1 as table_id FROM TABLE 1
UNION
SELECT ID,name,surname,2 as table_id FROM TABLE 2 )
SELECT name, surname
FROM cte_1
ORDER BY table_id,ID
simply use a UNION clause with out order by.
SELECT name,surname FROM TABLE 1
UNION
SELECT name,surname FROM TABLE 2
if you wanted to order first table use the below query.
;WITH cte_1
AS
(SELECT name,surname,ROW_NUMBER()OVER(ORDER BY Id)b FROM TABLE 1 )
SELECT name,surname
FROM cte_1
UNION
SELECT name,surname
FROM TABLE 2

select only columns with values not matching between two rows

Is it possible to get only columns which have different values in SQL SERVER?
TABLE 1
id Name Desig
1 Ali Assistant.Manager
1 Ali Manager
2 John Manager
Now if i want to check status of id 1, it should return Designation(i.e Assistant.Manager & Manager)
Try this:
SELECT T1.Desig
FROM TableName T1 JOIN
(SELECT id,name
FROM TableName
GROUP BY id,name
HAVING COUNT(DISTINCT Desig) > 1) T2
ON T1.id=T2.id AND T1.name=T2.name
Result:
DESIG
Assistant.Manager
Manager
See result in SQL Fiddle.
If id is an identity, as you comment, you can choose the latest row per name like:
select *
from (
select row_number() over (
partition by name
order by id desc) as rn
, *
) as SubQueryAlias
where rn = 1 -- Latest row per name

How to filter out records grouped by date with a large date difference

I have some records, grouped by name and date.
I would like to find any records in a table that have a date difference between them larger than a week, from the most recent record.
Would this be possible to do with a cte?
I am thinking something along these lines (it is difficult to explain)
; with mycte as (
select *
from #GroupedRecords)
select *
from mycte a
join (select *
from #GroupedRecords) b on a.Name = b.Name
where datediff(day, a.DateCreated, b.DateCreated) > 7
For example:
Id Name Date
1 Foo 02/03/2010
2 Bar 23/02/2010
3 Ram 21/01/2010
4 Foo 29/02/2010
5 Foo 22/02/2010
6 Foo 05/12/2009
The results should be:
Id Name Date
1 Foo 02/03/2010
5 Foo 22/02/2010
6 Foo 05/12/2009
You can try:
SELECT id,
name,
DATE
FROM groupedrecords AS gr1
WHERE ( (SELECT MAX(DATE) AS md
FROM groupedrecords gr2
WHERE gr1.name = gr2.name) - gr1.DATE ) > 7;
Or probably better yet:
SELECT id,
name,
DATE
FROM groupedrecords AS gr1
INNER JOIN (SELECT name,
MAX(DATE) AS md
FROM groupedrecords AS gr2
GROUP BY name) AS q1
ON gr1.name = q1.name
WHERE ( q1.md - gr1.DATE ) > 7;
UPDATE: As suggested in the comments, here is a version that uses union to get the id with the max date per group AND the ids of those that are 7 days or older than the max date. I used a CTE for fun, it was not necessary. Note that if there is more than 1 ID that shares the max date in a group, this query will need to be modified-
WITH CTE
AS (SELECT name,
Max(date) AS MD
FROM Records
GROUP BY name)
SELECT R.ID,
R.name,
R.date
FROM CTE
INNER JOIN Records AS R
ON CTE.Name = R.Name
AND CTE.MD = R.date
UNION ALL
SELECT r1.id,
r1.name,
r1.DATE
FROM Records AS R1
INNER JOIN CTE
ON CTE.name = R1.name
WHERE ( CTE.md - R1.DATE ) > 7
ORDER BY name ASC,
date DESC
I wonder if this gets close to a solution:
; with tableWithRow as (
select *, row_number() over (order by name, date) as rowNum
from t
)
select t1.*, t2.id t2id, t2.name t2name, t2.date t2date, t2.rowNum t2rowNum
from tableWithRow t1
join tableWithRow t2
on t1.rowNum = t2.rowNum + 1 and t1.name = t2.name