【问题标题】:SQL Query SUM DATEDIFF MAXSQL 查询 SUM DATEDIFF MAX
【发布时间】:2013-04-12 11:43:45
【问题描述】:

我的 SQL 查询有问题。我想计算使用过的应用程序的运行时间。但是在数据库中,日期值被插入不止一次。我只需要 pk_date 列的最大值,并且 starttime 列中没有重复的条目。

这是 SQL 查询:

SELECT DISTINCT Standortname,
DATEPART(YEAR,PK_Date) AS Jahr,
DATEPART(month,PK_Date) AS Monat,
Lizenzname,
COUNT(DISTINCT username) AS AnzahlUser,
SUM(DISTINCT DATEDIFF(minute,starttime ,pk_date))  AS RuntimeMinute,
endtime,
pk_date

FROM BenutzerLizenz,Benutzer,Abteilung,Lizenz,Standort
WHERE 
BenutzerLizenz.PK_ID_user=Benutzer.PK_ID_user
AND BenutzerLizenz.PK_ID_lic=Lizenz.PK_ID_lic
AND PK_ID_standort=FK_ID_standort
AND DATEPART(month,PK_Date) = '04'
AND DATEPART(YEAR,PK_Date) = '2013'
AND Lizenzname = 'iman_1st'
AND Standortname = 'Unterlüß'

GROUP BY
 Standortname,
 DATEPART(YEAR,PK_Date),
 DATEPART(month,PK_Date),
 Lizenzname,
 starttime,
 endtime,
 pk_date

结果如下:

... RuntimeMinute   starttime                   pk_date
    339         2013-04-11 11:05:00.0000000 2013-04-11 16:44:37.9650000
    346         2013-04-11 11:05:00.0000000 2013-04-11 16:51:25.4800000
    356         2013-04-11 11:05:00.0000000 2013-04-11 17:01:19.9670000
    475         2013-04-11 10:06:00.0000000 2013-04-11 18:01:15.6620000

上述前三个运行时来自同一个用户和会话,最后一个来自另一个用户和会话。我只想计算和总结同一开始时间的最后一次运行时间,插入的最大日期 (pk_date) -> 356 + 475 是我想要的值。

在另一个类似的查询中,所有值都是累积的(列 starttime、endtime、pk_date 不包含在其中,因此查询构建了所有用户的所有运行时值的总和)。我尝试使用 DISTINCT 和 MAX(pk_date) 但它没有按预期工作。我必须使用子查询吗?

【问题讨论】:

  • 哪些字段是用户和会话? - 使用@d'alar'cop 回答
  • @d'alar'cop user 是列用户名。这算在上面的选择中。我想要一份报告,例如其中 3 个用户每月使用 800 分钟的应用程序。对于会话,我的意思是具有相同开始时间的行。像上面的开始时间是 11:05 用户从 11:05 到 17:01 使用程序。我只需要 pk_date 最大值之间的时间(仅累积 356 + 475)。

标签: sql group-by sum datediff


【解决方案1】:

我会为此使用RANK() 函数。

SELECT * FROM
(
SELECT DISTINCT Standortname,
DATEPART(YEAR,PK_Date) AS Jahr,
DATEPART(month,PK_Date) AS Monat,
Lizenzname,
COUNT(DISTINCT username) AS AnzahlUser,
SUM(DISTINCT DATEDIFF(minute,starttime ,pk_date))  AS RuntimeMinute,
endtime,
pk_date,
RANK() Over (PARTITION BY username ORDER BY pk_date DESC) As Rank

FROM BenutzerLizenz,Benutzer,Abteilung,Lizenz,Standort
WHERE 
BenutzerLizenz.PK_ID_user=Benutzer.PK_ID_user
AND BenutzerLizenz.PK_ID_lic=Lizenz.PK_ID_lic
AND PK_ID_standort=FK_ID_standort
AND DATEPART(month,PK_Date) = '04'
AND DATEPART(YEAR,PK_Date) = '2013'
AND Lizenzname = 'iman_1st'
AND Standortname = 'Unterlüß'

GROUP BY
 Standortname,
 DATEPART(YEAR,PK_Date),
 DATEPART(month,PK_Date),
 Lizenzname,
 starttime,
 endtime,
 pk_date,
 username
) tmp where Rank=1

RANK() 函数按照ORDER BY 定义的顺序排列结果集的每一行。配合PARTITION BY使用,可以进一步划分数据进行排名。

由于您已经拥有所需的数据,您将按username 对结果进行分区并对pk_date 进行排名以获得最高的数据。

【讨论】:

  • 非常感谢。当我与 starttime 分开时,它工作得很好,因为用户每天可以登录超过一次,所以用户是相同的,但 starttime 不同(两条 rank1 行)。
  • 另一个问题:现在我得到每个用户使用应用程序一次的分钟数。我想累积每个许可证的所有用户的所有运行时间(user1 300 min + user2 400 min + user3 100min),但是当我添加另一个选择和求和此列时,我只能显示此求和列而不是其他值,因为我必须使用一个组
  • 是的。每次进行聚合(例如 SUM)时,都必须执行 GROUP BY。只需 GROUP BY 您要显示的所有其他字段。
  • 现在在您查询之前,我添加 SELECT Standortname, Jahr, Monat, Lizenzname, SUM(AnzahlUser) AS Users, SUM(DISTINCT RuntimeMinute) AS RuntimeAkku FROM( SELECT * FROM (... 并使用 group by现在我总结了不同的用户,但是当一个用户每天登录 2 次时,他将被计算 2 次。当我使用 DISTINCT 时,我只得到 1 个用户,但这个结果是错误的。
  • 我觉得你确实需要SELECT Standortname, Jahr, Monat, Lizenzname, COUNT(AnzahlUser) AS Users, SUM(RuntimeMinute) AS RuntimeAkku FROM (...) tmp2 GROUP BY Standortname, Jahr, Monat, Lizenzname
【解决方案2】:

听起来您想要进行一个查询,只保留每个开始时间和用户/会话组合的 max(pk_date)。然后将该查询添加到您的 FROM 子句(假设为 adhoc)。然后你把 WHERE 子句 pk_date = adhoc.pkdate AND username = adhoc.username etc...

简化示例:

(SELECT username, startdate, max(pk_date) as pk_date 
FROM <whatever> 
GROUP BY username, startdate) (= <new>)

现在,在您的主查询中...

SELECT ... FROM ...,<new> adhoc 
WHERE adhoc.username = username 
AND adhoc.startdate = startdate 
AND pk_date = adhoc.pk_date ... 

这有帮助吗?

【讨论】:

  • 在你的第一句话中,你准确地描述了我想要拥有的东西。但我不明白其余的 - 你能给我举个例子吗?如何向 from 子句添加查询以及查询中提到的内容?
  • 我已编辑 - 这将取决于您使用的 DBMS - 可能还有其他方式。埃特瓦斯克拉勒?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多