我对GROUP BY和INNER JOIN有一个小问题。我尝试将时间花在按用户分组的事件上,以查看抽动用户的效率。
此刻,我只收到错误消息
'列'XXX'在选择列表中无效,因为它既不包含在聚合函数中也不包含在GROUP BY子句中>
我了解SELECT语句中的所有字段在GROUP BY中都是必需的,但是如果我对所有这些字段进行分组,则不会收到我想要的内容。
我认为我的问题是因为我不正确地理解GROUP BY和INNER JOIN,所以我试图学习很多网站,但至少在此刻我看不到错误。
这是我的代码:
SELECT
id_incident_project AS ID,
i.title AS title,
companyname as social_name,
username as tech_name,
ia.DESCRIPTION_TEXT as description,
CONVERT(varchar, ia.ACTIONDATE, 101) as action_date,
CAST(TIME as INT) as acting_time,
CAST(actions_time as INT) AS total_time
FROM
incident i
INNER JOIN incident_0001 i1 ON i1.ID_INCIDENT = i.ID_INCIDENT
INNER JOIN incident_action ia ON ia.ID_INCIDENT = i.ID_INCIDENT
INNER JOIN agent a ON a.ID_AGENT = ia.ID_AGENT
INNER JOIN username u on u.ID_USERNAME = a.ID_USERNAME
WHERE
ia.ACTIONDATE BETWEEN '## START DATE (YYYYMMDD)##' AND '## END DATE (YYYYMMDD)##'
GROUP BY username
答案 0 :(得分:1)
SELECT
子句中未分组的所有列都必须经过聚合函数。要获取某物,您可以将其通过MAX
:
SELECT
MAX(id_incident_project) AS ID,
MAX(i.title) AS title,
MAX(companyname) as social_name,
username as tech_name,
MAX(ia.DESCRIPTION_TEXT) as description,
MAX(CONVERT(varchar, ia.ACTIONDATE, 101)) as action_date,
MAX(CAST(TIME as INT)) as acting_time,
MAX(CAST(actions_time as INT)) AS total_time
FROM
incident i
INNER JOIN incident_0001 i1 ON i1.ID_INCIDENT = i.ID_INCIDENT
INNER JOIN incident_action ia ON ia.ID_INCIDENT = i.ID_INCIDENT
INNER JOIN agent a ON a.ID_AGENT = ia.ID_AGENT
INNER JOIN username u on u.ID_USERNAME = a.ID_USERNAME
WHERE
ia.ACTIONDATE BETWEEN '## START DATE (YYYYMMDD)##' AND '## END DATE (YYYYMMDD)##'
GROUP BY username
但是,在所有联接完成之后,当同一username
有多个行时,此方法将冒着输出来自不同源行的值的风险。例如,如果用户名“ JohnSmith”发生(说)两次事件,一次事件发生在2019年1月1日,标题为“ Zombie Sighting”,第二次事件发生在2019-03-31,其标题为“ Aitch Dropping”,则“ “最高”标题将是“僵尸瞄准”,最晚日期是2019-03-31,因此针对不同事件。
为避免这种情况,您可以将GROUP BY
替换为username
上的分区,对事件进行排序,并以一致的方式为每个username
选择一个事件:
SELECT
ID, title, social_name, tech_name, description,
action_date, acting_time, total_time
FROM (
SELECT
id_incident_project) AS ID,
i.title AS title,
companyname as social_name,
username as tech_name,
ia.DESCRIPTION_TEXT) as description,
CONVERT(varchar, ia.ACTIONDATE, 101) as action_date,
CAST(TIME as INT) as acting_time,
CAST(actions_time as INT) AS total_time,
ROW_NUMBER () OVER (
PARTITION BY username
ORDER BY
ia.ACTIONDATE DESC, -- pick out latest
i1.ID_INCIDENT DESC -- tie breaker
) AS OrderNum
FROM
incident i
INNER JOIN incident_0001 i1 ON i1.ID_INCIDENT = i.ID_INCIDENT
INNER JOIN incident_action ia ON ia.ID_INCIDENT = i.ID_INCIDENT
INNER JOIN agent a ON a.ID_AGENT = ia.ID_AGENT
INNER JOIN username u on u.ID_USERNAME = a.ID_USERNAME
WHERE
ia.ACTIONDATE BETWEEN '## START DATE (YYYYMMDD)##' AND '## END DATE (YYYYMMDD)##'
) t
WHERE t.OrderNum = 1