【问题标题】:tSQL: Get average amount of time from record creation to first contacttSQL:获取从记录创建到第一次联系的平均时间
【发布时间】:2014-11-14 20:40:09
【问题描述】:

我有一个 CRM 数据库,其中包含主表列 createon (date) 和 createat (time)。我们称之为A表

有一个辅助表用于记录有关尝试联系在 A 中创建的记录的活动的数据,我们将此表称为 B。

我正在尝试编写一个 tSQL 查询,该查询将显示在 A 中创建记录与在 B 中记录第一个活动之间的平均时间。

这是我目前所拥有的:

SELECT
    B.userid,
    avg(cast(datediff(MINUTE, A.createat, B.ontime) as float)) 
    AS 'AVG TIME FROM LEAD CREATION TO FIRST LOGGED ACTIVITY'
FROM 
    TableA A, TableB B
WHERE 
    A.KEY_value = B.KEY_value
    AND B.USERID in ('USER1','USER2','USER3','USER4','USER5')
    AND B.ONDATE > '09/01/2014' 
GROUP BY 
    B.USERID
HAVING 
    B.ontime = min(B.ontime)

如果我删除 'have' 子句,查询将起作用,但我不能确定我是否获得了表 B 中第一个记录活动的时间 (min(B.ontime))

我仍然是 SQL 新手,因此我们将不胜感激任何帮助/指导!

【问题讨论】:

  • Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 ANSI 中的 proper ANSI JOIN 语法-92 SQL 标准(20 多年前),不鼓励使用它
  • @marc_s 很高兴知道。谢谢。
  • @marc_s:被谁气馁?
  • 所有喜欢让查询易于理解的人。
  • 使用 ANSI 联接有几个原因:可移植性、对联接与过滤的更精细控制、使用多个外部联接时的歧义性更小以及使用 UNION 联接的能力。

标签: sql sql-server tsql average


【解决方案1】:

一种方法是在子查询中为每个用户获取最短准时并加入表 A。

SELECT
    T.userid,
    ISNULL(avg(cast(datediff(MINUTE, cast(A.createat as datetime)+A.createdon, T.MinOnTime) as float)),0) 
    AS [AVG TIME FROM LEAD CREATION TO FIRST LOGGED ACTIVITY]
FROM 
TableA A
LEFT JOIN ( SELECT Key_value, userid, min(cast(B.ontime as datetime) + B.ondate) as MinOnTime FROM 
                TableB B
                WHERE B.USERID in ('USER1','USER2','USER3','USER4','USER5')
                      AND B.ONDATE > '09/01/2014' 
                GROUP BY KEY_Value, userid
              )  T
on  A.KEY_value = T.KEY_value
GROUP BY T.userid

【讨论】:

  • 在我在末尾添加了一个 GROUP BY 子句后,这似乎有效,但我有一个用户的聚合值为负。对于未在与 A.createon 日期相同的日期在 B 中记录活动的用户,我该如何解释?
  • 如果 Op 的平均值为负,这是否意味着 op 键没有正确排列时间?在创建时间之前第一个记录的活动如何?
  • @RADAR 我可以将 a.createon+a.createat AS [CreateDateTime](以分钟为单位)和 T.MinOnDate+T.MinOnTime AS [MinOnDateTime](以分钟为单位)相加并使用变量ISNULL(avg(cast(datediff(MINUTE, CreateDateTime, MinOnDateTime) as float)),0)
  • @lookslikeanevo 我认为我们需要考虑创建日期和活动日期...(见上文)
  • @jer_bear,是ontime整数还是日期时间,是只存储时间分量还是分钟
【解决方案2】:
    SELECT
        t.userid
        ,case when A.createon = B.ondate then avg(cast(datediff(MINUTE, A.createat, B.ontime) as float))
            else avg(datediff(MINUTE, A.createon, B.ondate)+(cast(datediff(MINUTE, A.createat, B.ontime) as float)))
                end  as 'AVG TIME FROM LEAD CREATION TO FIRST LOGGED ACTIVITY'
    FROM 
    TableA a
        LEFT JOIN ( SELECT Key_value, userid, min(B.ontime) as MinOnTime 
                    FROM TableB b
                    WHERE b.USERID in ('USER1','USER2','USER3','USER4','USER5')
                          and b.ondate > '2014/09/01' 

                    GROUP BY KEY_Value, userid) t on a.KEY_value = t.KEY_value
GROUP BY 
t.userid

【讨论】:

  • 我必须考虑创建日期和日期。 createat 和 ontime 时间存储为 varchar() 值,而 ondate 和 createon 日期存储为 datetime()。我可以有一个 createat 时间为 [13:00] 的记录(即该记录是在下午 1:00 创建的)但在第二天的 [12:00] 有一个准时(即第一个记录的活动直到次日中午 12:00)。在这种情况下,我最终会得到一个负的总值。必须考虑到 datetime() 字段。
  • @jer_bear 好的,知道了...将很快修改并添加一个案例声明
  • @lookslikeanevo 作为仅供参考,您可以删除一个答案,以便在您修改它时不会显示它,然后在完成修改后取消删除它。
  • @jer_bear 你有任何样本数据可以测试输出吗?
  • @lookslikeanevo 不,不幸的是我没有。我不知道即使我有它,我怎么会给你一些。我可以从表 A 和 B 中选择 * 前 x 行并将其发送给您吗?
【解决方案3】:
SELECT
    B.userid,
    avg(cast(datediff(MINUTE, A.createat, min(B.ontime)) as float)) 
    AS 'AVG TIME FROM LEAD CREATION TO FIRST LOGGED ACTIVITY'
FROM 
    TableA A, TableB B
WHERE 
    A.KEY_value = B.KEY_value
    AND B.USERID in ('USER1','USER2','USER3','USER4','USER5')
    AND B.ONDATE > '09/01/2014' 
GROUP BY 
    B.USERID

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多