GROUP BY

时间:2016-04-17 19:38:06

标签: sql sql-server-2008

我创建了一个SQL小提琴(http://sqlfiddle.com/#!9/e0536/1),其中包含了我正在工作的类似数据(表中实际上有更多列)。表包含就业详细信息。员工可以在表格中有多个记录(几个固定期限合同)以及不同的employee_ID(从' tixxxxx'变为' pixxxxx')。 PESEL号码是唯一的个人识别号码。过去合同的ID可能高于实际合同的ID,因为表格每天都会填充数据作为基于HR数据的摘录。

我需要得到的是:

  • 至少是最新的employee_ID(expirationdate最大的行)
  • 包含最新employee_ID所有列的整行
  • 最好是我能获得最新的employee_ID整行,包括第一个startdate(如果员工有多个合同,则很重要)

自从我每天使用SQL以来已经有一段时间了,所以我很感激这里的任何帮助。我想到了一些带有group by子句的嵌套查询,但我从未理解过相关的子查询。

预期结果:

ID          Employee_ID PESEL       StartDate  ExpirationDate
----------- ----------- ----------- ---------- --------------
1           pi39764     1111        2014-01-01 2016-06-01
2           pi12986     1234        2015-12-01 2099-12-31
5           pi12345     4321        2015-02-01 2099-12-31

其中startdate是第一个startdate。

4 个答案:

答案 0 :(得分:2)

SELECT e1.employee_id, e.pesel, e.maxdate
FROM (
      SELECT pesel, MAX(expirationdate) as maxdate
      FROM employees
      GROUP BY pesel
) e
INNER JOIN employees e1
ON e.pesel = e1.pesel AND e.maxdate = e1.expirationdate

输出:

| Employee_ID | pesel |                    maxdate |
|-------------|-------|----------------------------|
|     pi39764 |  1111 |     June, 01 2016 00:00:00 |
|     pi12986 |  1234 | December, 31 2099 00:00:00 |
|     pi12345 |  4321 | December, 31 2099 00:00:00 |

要查找每个PESEL的第一个日期和最后一个日期,请使用:

SELECT e1.employee_id, e.pesel, e.startdate, e.enddate
FROM (
      SELECT pesel, 
           MIN(startdate) as startdate, 
           MAX(expirationdate) as enddate
      FROM employees
      GROUP BY pesel
) e
INNER JOIN employees e1
ON e.pesel = e1.pesel AND e.enddate = e1.expirationdate

答案 1 :(得分:1)

可能你正在寻找这样的查询:

SELECT e.*, CASE WHEN actual = StartDate THEN 1 ELSE 0 END AS actual_e, first_startdate
FROM Employees AS e
INNER JOIN(SELECT PESEL, MIN(startdate) AS first_startdate , MAX(startdate) AS actual 
  FROM Employees AS e
  GROUP BY PESEL) AS g
  ON g.PESEL = e.PESEL

编辑:
获取每行的实际Employee_ID使用子查询:

, CASE WHEN actual = StartDate THEN null 
ELSE (SELECT max(a.Employee_ID) FROM Employees AS a WHERE a.PESEL = e.PESEL and a.StartDate = actual)
END AS actual_Employee_ID

编辑:
在Fidde你编写MySQL查询,对于sql server(tag)来说它是最简单的:

SELECT e.*
, LEAD(Employee_ID) OVER (PARTITION BY PESEL ORDER BY startdate) actual_Employee_ID
, MIN(startdate) OVER (PARTITION BY PESEL) first_startdate
FROM Employees AS e

编辑(最后一个结果):
对于所有数据:

SELECT e.*
, first_startdate
, last_t_startdate
, last_startdate
, (SELECT max(employee_ID) FROM dbo.Employees t WHERE startdate = last_t_startdate AND PESEL = e.PESEL) AS last_t_id
, (SELECT max(employee_ID) FROM dbo.Employees t WHERE startdate = last_startdate AND PESEL = e.PESEL) AS last_id
FROM dbo.Employees AS e
OUTER APPLY (
  SELECT Min(startdate) AS first_startdate
  , Max(Case When employee_ID LIKE 'ti%' Then startdate End) last_t_startdate
  , Max(startdate) AS last_startdate    
  FROM dbo.Employees
  WHERE PESEL = e.PESEL
  --GROUP BY PESEL
  ) AS g 

输出:

ID  Employee_ID PESEL   StartDate   ExpirationDate  first_startdate last_t_startdate    last_startdate  last_t_id   last_id
1   pi39764 1111    2015-01-01  2016-06-01  2014-01-01  2014-01-01  2015-01-01  ti00001 pi39764
2   pi12986 1234    2015-12-01  2099-12-31  2015-12-01  NULL    2015-12-01  NULL    pi12986
3   ti00001 1111    2014-01-01  2014-12-31  2014-01-01  2014-01-01  2015-01-01  ti00001 pi39764
4   pi12345 4321    2015-02-01  2015-06-30  2015-02-01  NULL    2016-01-01  NULL    pi12345
5   pi12345 4321    2016-01-01  2099-12-31  2015-02-01  NULL    2016-01-01  NULL    pi12345
6   pi12345 4321    2015-07-01  2015-12-31  2015-02-01  NULL    2016-01-01  NULL    pi12345

分组数据:

SELECT pesel
, first_startdate
, last_t_startdate
, last_startdate
, (SELECT max(employee_ID) FROM dbo.Employees t WHERE startdate = last_t_startdate AND PESEL = g.PESEL) last_t_id
, (SELECT max(employee_ID) FROM dbo.Employees t WHERE startdate = last_startdate AND PESEL = g.PESEL) last_id
FROM (
  SELECT PESEL
  , Min(startdate) AS first_startdate
  , Max(Case When employee_ID LIKE 'ti%' Then startdate End) AS last_t_startdate 
  , Max(startdate) AS last_startdate
  FROM dbo.Employees
  GROUP BY PESEL) AS g

输出:

pesel   first_startdate last_t_startdate    last_startdate  last_t_id   last_id
1111    2014-01-01  2014-01-01  2015-01-01  ti00001 pi39764
1234    2015-12-01  NULL    2015-12-01  NULL    pi12986
4321    2015-02-01  NULL    2016-01-01  NULL    pi12345

答案 2 :(得分:1)

使用SUBTRING_INDEX和GROUP_CONCAT技巧获取所有列

select SUBSTRING_INDEX(GROUP_CONCAT(Employee_ID ORDER BY StartDate DESC),',',1),
PESEL,MIN(StartDate),MAX(ExpirationDate)
from employees
GROUP BY PESEL
ORDER BY 2

答案 3 :(得分:1)

所以试试这个:

IArchive rar = SharpCompress.Archive.Rar.RarArchive.Open(new FileInfo("ze.rar"), SharpCompress.Common.Options.None);
        rar.WriteToDirectory(Directory.GetCurrentDirectory() + "\\DATA", SharpCompress.Common.ExtractOptions.Overwrite);

然后你得到:

SELECT ID, Employee_ID, PESEL, first_startdate AS StartDate, ExpirationDate
FROM (
    SELECT e.*
    , LEAD (Employee_ID) OVER (PARTITION BY PESEL ORDER BY startdate) actual_Employee_ID
    , MIN(startdate) OVER (PARTITION BY PESEL) first_startdate
    FROM Employees AS e) AS x
WHERE actual_Employee_ID is null

http://sqlfiddle.com/#!3/e0536/7