Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL-选择已结束最新合同但有其他合同打开的员工_Sql_Sql Server - Fatal编程技术网

SQL-选择已结束最新合同但有其他合同打开的员工

SQL-选择已结束最新合同但有其他合同打开的员工,sql,sql-server,Sql,Sql Server,我一直在兜圈子,想弄明白这一点 我试图选择那些已经结束了最近一份合同但仍有前一份有效合同的员工 例如,一名员工有多份合同,其中一些可能是临时合同或兼职合同——这与此无关,但会终止其最近的合同,但是,他们仍然保留在旧合同中 请参阅下表,了解我试图实现的目标-相关字段: +------+-------------+-------------+------------+------------+ | ID | CONTRACT_ID | EMPLOYEE_ID | START_DATE | END

我一直在兜圈子,想弄明白这一点

我试图选择那些已经结束了最近一份合同但仍有前一份有效合同的员工

例如,一名员工有多份合同,其中一些可能是临时合同或兼职合同——这与此无关,但会终止其最近的合同,但是,他们仍然保留在旧合同中

请参阅下表,了解我试图实现的目标-相关字段:

+------+-------------+-------------+------------+------------+
| ID   | CONTRACT_ID | EMPLOYEE_ID | START_DATE | END_DATE   |
+------+-------------+-------------+------------+------------+
| 4321 | 974         | 321         | 21/01/2004 | 31/12/2016 |
+------+-------------+-------------+------------+------------+
| 4322 | 1485        | 321         | 09/01/2009 | 31/08/2014 |
+------+-------------+-------------+------------+------------+
| 4323 | NULL        | 321         | 25/07/2009 | 31/01/2010 |
+------+-------------+-------------+------------+------------+
| 4324 | 2440        | 321         | 01/06/2012 | NULL       |
+------+-------------+-------------+------------+------------+
| 4325 | 7368        | 321         | 01/01/2017 | NULL       |
+------+-------------+-------------+------------+------------+
| 4326 | 7612        | 321         | 14/02/2017 | 06/06/2017 |
+------+-------------+-------------+------------+------------+
以下是我目前拥有的代码,它没有返回正确的数据:

select
cond.EMPLOYEE_ID
,cond.END_DATE

from
contracts as cond

join
(select

EMPLOYEE_ID
,START_DATE
,END_DATE

from
contracts

where
END_DATE is null) a on a.EMPLOYEE_ID = cond.employee_id and a.START_DATE <     
cond.END_DATE

group by cond.end_date, cond.EMPLOYEE_ID

having
max(cond.START_DATE) is not null AND cond.END_DATE is not null
正如您所看到的,最近的合同没有结束日期,但有一个打开的合同


非常感谢您的帮助。

我不是SQL server专家,但您可以尝试类似的方法:

SELECT *
FROM   contracts cont
WHERE  cont.end_date IS NOT NULL
  AND  cont.end_date <= SYSDATE
  AND  NOT EXISTS (SELECT *
                   FROM   contracts recent
                   WHERE  recent.employee_id = cont.employee_id
                     AND  recent.start_date > cont.start_date)
  AND  EXISTS (SELECT *
               FROM   contracts openc
               WHERE  openc.employee_id = cont.employee_id
                 AND  (openc.end_date IS NULL OR openc.end_date > SYSDATE))
前两个条件搜索已结束的合同。 下一个不存在确保所选合同是最新的合同。 最后一部分确保存在其他未结合同。

您可以使用行号和CTE来执行此操作

在行动中看到它:

在下面的代码中,我更改了dateformat,您可能不必这样做

set dateformat dmy
declare @table table (ID int,CONTRACT_ID int, EMPLOYEE_ID int, [START_DATE] datetime,   END_DATE datetime)
insert into @table
values
(4321,974,321,'21/01/2004','31/12/2016'),
(4322,1485,321,'09/01/2009','31/08/2014'),
(4323,NULL,321,'25/07/2009','31/01/2010'),
(4324,2440,321,'01/06/2012',NULL),
(4325,7368,321,'01/01/2017',NULL),
(4326,7612,321,'14/02/2017','06/06/2017')

--this applies a row_number to each contract per employee
--the most recent contract (by start date) gets a 1
;with cte as(
    select
        EMPLOYEE_ID
        ,ID
        ,row_number() over (partition by EMPLOYEE_ID order by [START_DATE] desc) as ContractRecentcy
    from @table)


--this will return all contacts that are open, which aren't the most recent for the employee.
select
    t.*
from 
    @table t
where
    t.END_DATE is null
    and t.ID not in (select ID from cte where ContractRecentcy = 1)

set dateformat mdy
使用窗口聚合函数count获取最近的开始日期、结束日期和未结合同的计数:

使用一些其他情况测试设置:

create table contracts (id int, contract_id int, employee_id int, start_date date, end_date date);
insert into contracts values
 (4321, 974, 321, '20040121', '20161231')
,(4322, 1485, 321, '20090109', '20140831')
,(4323, null, 321, '20090725', '20100131')
,(4324, 2440, 321, '20120601', null)
,(4325, 7368, 321, '20170101', null)
,(4326, 7612, 321, '20170214', '20170606')
,(1, 1, 1, '20160101', null)
,(2, 2, 1, '20160701', '20161231')
,(3, 3, 1, '20170101', null)        /* most recent is open, do not return */
,(4, 4, 2, '20160101', '20170630')
,(5, 5, 2, '20160701', '20161231')
,(6, 6, 2, '20170101', '20170630')  /* most recent is closed, no others open, do not return */
,(7, 7, 3, '20160101', '20170630')
,(8, 8, 3, '20160701', null)
,(9, 9, 3, '20170101', '20170630')  /* most recent is closed, one other open, return */
;
rextester演示:

返回:

+------+-------------+-------------+------------+------------+----------------+--------------+----------------+
|  id  | contract_id | employee_id | start_date |  end_date  | max_start_date | max_end_date | open_contracts |
+------+-------------+-------------+------------+------------+----------------+--------------+----------------+
|    7 | 7           |           3 | 2016-01-01 | 2017-06-30 | 2017-01-01     | 2017-06-30   |              1 |
|    8 | 8           |           3 | 2016-07-01 | NULL       | 2017-01-01     | 2017-06-30   |              1 |
|    9 | 9           |           3 | 2017-01-01 | 2017-06-30 | 2017-01-01     | 2017-06-30   |              1 |
| 4321 | 974         |         321 | 2004-01-21 | 2016-12-31 | 2017-02-14     | 2017-06-06   |              2 |
| 4322 | 1485        |         321 | 2009-01-09 | 2014-08-31 | 2017-02-14     | 2017-06-06   |              2 |
| 4323 | NULL        |         321 | 2009-07-25 | 2010-01-31 | 2017-02-14     | 2017-06-06   |              2 |
| 4324 | 2440        |         321 | 2012-06-01 | NULL       | 2017-02-14     | 2017-06-06   |              2 |
| 4325 | 7368        |         321 | 2017-01-01 | NULL       | 2017-02-14     | 2017-06-06   |              2 |
| 4326 | 7612        |         321 | 2017-02-14 | 2017-06-06 | 2017-02-14     | 2017-06-06   |              2 |
+------+-------------+-------------+------------+------------+----------------+--------------+----------------+
试试这个家伙

SELECT [EMPLOYEE_ID]

FROM [contracts]

WHERE [END_DATE] IS NULL

AND [EMPLOYEE_ID] IN (SELECT B.[EMPLOYEE_ID] FROM (
SELECT * FROM (
SELECT RowN = Row_Number() over (partition by [EMPLOYEE_ID] ORDER BY[START_DATE] DESC)
, [EMPLOYEE_ID]
, [CONTRACT_ID]
, [END_DATE]

FROM [contracts]

) A
WHERE A.[END_DATE] IS NOT NULL
AND A.[RowN] = 1) B)

抱歉,忘记将此添加到帖子中。SQL Server 2012是否也可以发布预期结果?请参见第一个表了解预期结果。产生此结果的输入是什么?这就是我试图实现的目标,因此,我提出了问题。由于重复,我在distinct中添加了更新。更新2这似乎错过了在同一天开始签订多份合同的员工。这是最好的解决方案,可以解决所有问题。提供的另外两个解决方案没有考虑到在同一日期开始的多个合同,这在这里发生得相当多。谢谢!谢谢你的解决方案。然而,它似乎并没有从发布的其他解决方案中收回那么多正确的结果。我认为这与同一天开始的多份合同有关。
+------+-------------+-------------+------------+------------+----------------+--------------+----------------+
|  id  | contract_id | employee_id | start_date |  end_date  | max_start_date | max_end_date | open_contracts |
+------+-------------+-------------+------------+------------+----------------+--------------+----------------+
|    7 | 7           |           3 | 2016-01-01 | 2017-06-30 | 2017-01-01     | 2017-06-30   |              1 |
|    8 | 8           |           3 | 2016-07-01 | NULL       | 2017-01-01     | 2017-06-30   |              1 |
|    9 | 9           |           3 | 2017-01-01 | 2017-06-30 | 2017-01-01     | 2017-06-30   |              1 |
| 4321 | 974         |         321 | 2004-01-21 | 2016-12-31 | 2017-02-14     | 2017-06-06   |              2 |
| 4322 | 1485        |         321 | 2009-01-09 | 2014-08-31 | 2017-02-14     | 2017-06-06   |              2 |
| 4323 | NULL        |         321 | 2009-07-25 | 2010-01-31 | 2017-02-14     | 2017-06-06   |              2 |
| 4324 | 2440        |         321 | 2012-06-01 | NULL       | 2017-02-14     | 2017-06-06   |              2 |
| 4325 | 7368        |         321 | 2017-01-01 | NULL       | 2017-02-14     | 2017-06-06   |              2 |
| 4326 | 7612        |         321 | 2017-02-14 | 2017-06-06 | 2017-02-14     | 2017-06-06   |              2 |
+------+-------------+-------------+------------+------------+----------------+--------------+----------------+
SELECT [EMPLOYEE_ID]

FROM [contracts]

WHERE [END_DATE] IS NULL

AND [EMPLOYEE_ID] IN (SELECT B.[EMPLOYEE_ID] FROM (
SELECT * FROM (
SELECT RowN = Row_Number() over (partition by [EMPLOYEE_ID] ORDER BY[START_DATE] DESC)
, [EMPLOYEE_ID]
, [CONTRACT_ID]
, [END_DATE]

FROM [contracts]

) A
WHERE A.[END_DATE] IS NOT NULL
AND A.[RowN] = 1) B)