我是SQL的初学者,我希望你们有人能帮助我渡过难关。
以下数据应按客户,日期和用户ID(我已经实现)进行分组。
Client User ID Date Action Module
Moha Mother 01/10/2010 12:35:36 PM Login PP
Moha Voodoo 02/10/2010 05:15:28 PM Login PP
Moha Panther 04/10/2010 04:36:42 PM Login PP
Moha Mother 01/10/2010 12:42:35 PM Some Action PP
Moha Mother 01/10/2010 12:55:14 PM Some Action PP
Moha Voodoo 02/10/2010 06:35:46 PM Login PP
Moha Panther 04/10/2010 04:53:24 PM Some Action PP
Moha Deuce 05/10/2010 09:13:42 PM Login PP
Moha Deuce 05/10/2010 09:19:42 PM Some Action PP
Moha Panther 06/10/2010 08:11:22 PM Login PP
Moha Deuce 05/10/2010 09:27:49 PM Some Action PP
Moha Panther 06/10/2010 08:15:18 PM Some Action PP
Moha Panther 06/10/2010 08:44:53 PM Some Action PP
Moha Deuce 05/10/2010 09:27:49 PM Login PP
Moha Rabbit 05/20/2010 09:27:49 PM Login PP
Moha Voodoo 02/10/2010 06:57:35 PM Some Action PP
Moha Deuce 06/10/2010 08:30:59 AM Login PP
Moha Rabbit 05/21/2010 09:27:49 PM Login PP
Moha Mother 03/10/2010 01:04:54 PM Login PP
Moha Mother 03/10/2010 01:23:55 PM Some Action PP
Moha Mother 03/10/2010 02:25:46 PM Login PP
Moha Mother 03/10/2010 02:45:54 PM Some Action PP
一旦完成,我想知道以下信息是否可以通过SQL实现。
客户用户ID日期登录Cnt登录Amt(分钟) Moha Mother 01/10/2010 1 19.6(00:06:59 + 00:12:39) - 支架信息不需要 Moha Mother 03/10/2010 2 39.2(00:19:01 + 00:20:08) Moha Vodoo ...... ...... 摩哈...... ...... ......
我已经编写了一个程序,它将动态接受客户端,开始日期,结束日期和用户ID的可选参数。我的过程将首先将日期转换为varchar格式并仅提取分组日期,然后使用case语句计算登录计数。但..!!如何计算2个连续条目之间的时间差并获得登录计数与分组规则完全一致?是否可以使用游标实现相同的目标?
请考虑提出任何问题并就上述主题提出任何建议,因为这是我的关键要求之一。先谢谢大家。
由于 CS
答案 0 :(得分:1)
这个问题有多种解决方案。
首先,我必须说我无法为您提供完整的解决方案。登录计数很容易,但对于每个用户的登录持续时间,我需要更多信息。根据目前的数据,尚不清楚哪个日期表示注销时间。假设在新登录之前它是最后一次出现'Some Action',那么解决方案就有可能,但我不知道这个假设是否正确。如果用户并行打开多个会话,则此假设将中断,并且如果未记录注销时间(例如,当会话在某个点之后超时并且未存储时间时),则您无能为力。< / p>
无论如何,我想提出三点:
第一点:您建议使用游标和存储过程来确定登录计数。这个解决方案可行,但通常是如何继续使用普通的编程语言,例如C或Pascal:在数据上定义一个for循环,并为每一行进行计算或例程。在SQL中,通常建议采用不同的方式。仅在必要时使用游标和循环,否则使用基于集合的解决方案。原因是基于集合的查询更容易针对SQL解释器进行优化。这个论点在其他地方的几篇文章中令人信服地提出,例如:Why are relational set-based queries better than cursors?
那么如何以“基于集合”的方式进行?从登录计数开始,您可以执行以下操作:
SELECT user, COUNT(*)
FROM YourTable
WHERE Action = 'Login'
GROUP BY user
这将返回每个用户的登录次数。如果您想要在特定时间段内登录的次数,可以在WHERE
字段中添加日期标准,如果您需要,例如。每个客户或每天登录的次数,您需要将Client
或CAST(Date) AS DATE
字段添加到SELECT
和GROUP BY
子句中。
最后关于登录持续时间,您的问题是如何计算两个连续条目之间的时差,这确实是应该如何完成的。在MSSQL中,我会使用ROW_NUMBER()
执行此操作(尽管可能有更好的解决方案适用于您的特定情况):
WITH NumberedTable AS (
SELECT User, Date, ROW_NUMBER() OVER (PARTITION BY User ORDER BY Date) AS LoginOccurrenceSortedByDate
FROM YourTable
WHERE Action = 'Login'
)
SELECT L.User, L.Date, DATEDIFF(seconds, R.Date, L.Date) AS DifferenceWithPreviousLogin
FROM NumberedTable L
LEFT JOIN NumberedTable R
ON R.LoginOccurrenceSortedByDate = L.LoginOccurrenceSortedByDate - 1
您基本上LEFT JOIN
每个条目与前一次出现并计算时差。