使用GROUP BY的SQL Server查询

时间:2013-01-30 15:55:45

标签: sql sql-server

我在编写查询时遇到问题,该查询将选择所有技能,加入员工和能力记录,但每位员工只返回一项技能,即他们最新的技能。使用此样本数据集

Skills
======
id   employee_id   competency_id   created
1    1             1               Jan 1
2    2             2               Jan 1
3    1             2               Jan 3

Employees
===========
id   first_name   last_name
1    Mike         Jones
2    Steve        Smith


Competencies
============
id   title
1    Problem Solving
2    Compassion

我想检索以下数据

Skill.id   Skill.employee_id   Skill.competency_id   Skill.created   Employee.id   Employee.first_name   Employee.last_name   Competency.id   Competency.title
2          2                   2                     Jan 1           2             Steve                 Smith                2               Compassion
3          1                   2                     Jan 3           1             Mike                  Jones                2               Compassion

我能够选择使用

创建的employee_id和max
SELECT MAX(created) as created, employee_id  FROM skills GROUP BY employee_id

但是当我开始在select语句中添加更多字段或添加一个连接时,我得到'列'xyz'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。 “错误。

感谢任何帮助,我不必使用GROUP BY,这正是我所熟悉的。

4 个答案:

答案 0 :(得分:3)

您获得的错误是因为如果使用了聚合函数,SQL Server要求SELECT列表中的任何项都包含在GROUP BY中。

问题在于,您可能在某些列中具有唯一值,这些值可能会导致结果失效。因此,您需要重写查询以使用以下方法之一:

您可以使用子查询来获得此结果。这将获得子查询中的max(created),然后您使用该结果来获取正确的员工记录:

select s.id SkillId,
  s.employee_id,
  s.competency_id,
  s.created,
  e.id employee,
  e.first_name,
  e.last_name,
  c.id competency,
  c.title
from Employees e
left join Skills s
  on e.id = s.employee_id
inner join
(
  SELECT MAX(created) as created, employee_id  
  FROM skills 
  GROUP BY employee_id
) s1
  on s.employee_id = s1.employee_id
  and s.created = s1.created
left join Competencies c
  on s.competency_id  = c.id

请参阅SQL Fiddle with Demo

或者另一种方法是使用row_number()

select *
from
(
  select s.id SkillId,
    s.employee_id,
    s.competency_id,
    s.created,
    e.id employee,
    e.first_name,
    e.last_name,
    c.id competency,
    c.title,
    row_number() over(partition by s.employee_id 
                      order by s.created desc) rn
  from Employees e
  left join Skills s
    on e.id = s.employee_id
  left join Competencies c
    on s.competency_id  = c.id
) src
where rn = 1

请参阅SQL Fiddle with Demo

答案 1 :(得分:1)

对于您添加到SELECT语句的每个非汇总列,您需要更新GROUP BY以包含它。

article可能会帮助您了解原因。

答案 2 :(得分:0)

;WITH
MAX_SKILL_created AS
(
    SELECT
        MAX(skills.created) as created,
        skills.employee_id
    FROM
        skills
    GROUP BY
        skills.employee_id
),
MAX_SKILL_id AS
(
    SELECT
        MAX(skills.id) as id,
        skills.employee_id
    FROM
        skills
        INNER JOIN MAX_SKILL_created
            ON MAX_SKILL_created.employee_id = skills.employee_id
            AND MAX_SKILL_created.created = skills.created
    GROUP BY
        skills.employee_id
)
SELECT
    * -- type all your columns here
FROM
    employees
    INNER JOIN MAX_SKILL_id
        ON MAX_SKILL_id.employee_id = employees.employee_id
    INNER JOIN skills
        ON skills.id = MAX_SKILL_id.id
    INNER JOIN competencies
        ON competencies.id = skills.competency_id

答案 3 :(得分:0)

如果您使用的是SQL Server,则可以使用OUTER APPLY

SELECT *
FROM employees E
OUTER APPLY (
    SELECT TOP 1 *
    FROM skills
    WHERE employee_id = E.id
    ORDER BY created DESC
) S
INNER JOIN competencies C
    ON C.id = S.competency_id