2009-10-23 7 views
7

ウェブページがロードされるたびにuserid、course、sessionid、およびrequestdateを記録するテーブルがあります。 私は与えられたcourseidのユーザIDあたりの期間を計算したいと思います。 重複するタイムパンにより、これを行うのは問題があります。ログテーブルから訪問期間の一部を計算するSQLクエリ

ここに提供されたデータは、コース1の期間中にユーザー1人あたり10分かかるはずです。 私はこの権利を得ることはできません。

CREATE TABLE PageLogSample (
    id INT NOT NULL PRIMARY KEY IDENTITY 
, userid INT 
, courseid INT 
, sessionid INT 
, requestdate DATETIME 
); 

TRUNCATE TABLE PageLogSample; 

INSERT INTO PageLogSample (userid, courseid, sessionid, requestdate) 
-- [0, 10] = 10 minutes 
      SELECT 1, 1, 1, '00:00:00' 
UNION ALL SELECT 1, 1, 1, '00:10:00' 
-- [0, 12] - [3, 5] = 10 minutes 
-- or ... [0, 3] + [5, 12] = 10 minutes 
UNION ALL SELECT 2, 1, 2, '00:00:00' 
UNION ALL SELECT 2, 2, 2, '00:03:00' 
UNION ALL SELECT 2, 2, 2, '00:05:00' 
UNION ALL SELECT 2, 1, 2, '00:12:00' 
-- [0, 12] - [3, 5] = 10 minutes 
-- or ... [0, 3] + [5, 12] = 10 minutes 
UNION ALL SELECT 3, 1, 3, '00:00:00' 
UNION ALL SELECT 3, 2, 3, '00:03:00' 
UNION ALL SELECT 3, 2, 3, '00:05:00' 
UNION ALL SELECT 3, 1, 3, '00:12:00' 
UNION ALL SELECT 3, 2, 3, '00:15:00' 
-- [1, 13] - [3, 5] = 10 minutes 
-- or ... [1, 3] + [5, 13] = 10 minutes 
UNION ALL SELECT 4, 2, 4, '00:00:00' 
UNION ALL SELECT 4, 1, 4, '00:01:00' 
UNION ALL SELECT 4, 2, 4, '00:03:00' 
UNION ALL SELECT 4, 2, 4, '00:05:00' 
UNION ALL SELECT 4, 1, 4, '00:13:00' 
UNION ALL SELECT 4, 2, 4, '00:15:00' 
-- [0, 5] + [10, 15] = 10 minutes 
UNION ALL SELECT 5, 1, 5, '00:00:00' 
UNION ALL SELECT 5, 1, 5, '00:05:00' 
UNION ALL SELECT 5, 1, 6, '00:10:00' 
UNION ALL SELECT 5, 1, 6, '00:15:00' 
-- [0, 10] = 10 minutes (ignoring everything inbetween) 
UNION ALL SELECT 6, 1, 7, '00:00:00' 
UNION ALL SELECT 6, 1, 7, '00:03:00' 
UNION ALL SELECT 6, 1, 7, '00:05:00' 
UNION ALL SELECT 6, 1, 7, '00:07:00' 
UNION ALL SELECT 6, 1, 7, '00:10:00' 
-- [0, 11] - [5, 6] = 10 minutes 
-- or ... [0, 3] + [7, 11] = 6 minutes (good) 
-- or ... [0, 5] + [7, 11] = 9 minutes (better) 
UNION ALL SELECT 7, 1, 8, '00:00:00' 
UNION ALL SELECT 7, 1, 8, '00:03:00' 
UNION ALL SELECT 7, 2, 8, '00:05:00' 
UNION ALL SELECT 7, 2, 8, '00:06:00' 
UNION ALL SELECT 7, 1, 8, '00:07:00' 
UNION ALL SELECT 7, 1, 8, '00:11:00' 
-- [0, 1] + [2, 4] + [5, 7] + [8, 13] = 10 
UNION ALL SELECT 8, 1, 9, '00:00:00' 
UNION ALL SELECT 8, 2, 9, '00:01:00' 
UNION ALL SELECT 8, 1, 9, '00:02:00' 
UNION ALL SELECT 8, 1, 9, '00:03:00' 
UNION ALL SELECT 8, 2, 9, '00:04:00' 
UNION ALL SELECT 8, 1, 9, '00:05:00' 
UNION ALL SELECT 8, 1, 9, '00:06:00' 
UNION ALL SELECT 8, 2, 9, '00:07:00' 
UNION ALL SELECT 8, 1, 9, '00:08:00' 
UNION ALL SELECT 8, 1, 9, '00:13:00' 
; 

最初にナイーブなアプローチを試みます。これにより、セッションの一部が重複している間違いが生じます。

DECLARE @courseid INT; 
SET @courseid = 1; 

SELECT subquery.userid 
, COUNT(DISTINCT subquery.sessionid) AS sessioncount 
, SUM(subquery.duration) AS duration 
, CASE SUM(subquery.duration) 
    WHEN 10 THEN 'ok' 
    ELSE 'ERROR' 
END 
FROM (
    SELECT userid 
    , sessionid 
    , DATEDIFF(MINUTE, MIN(requestdate), MAX(requestdate)) AS duration 
    FROM PageLogSample 
    WHERE courseid = @courseid 
    GROUP BY userid 
    , sessionid 
) subquery 
GROUP BY subquery.userid 
ORDER BY subquery.userid; 

-- userid sessioncount duration 
-- 1  1    10  ok 
-- 2  1    12  ERROR 
-- 3  1    12  ERROR 
-- 4  1    12  ERROR 
-- 5  2    10  ok 

2回目。重複を避ける。これは部分的にしか機能しません。

DECLARE @courseid INT; 
SET @courseid = 1; 

WITH cte (userid, courseid, sessionid, start, finish, duration) 
AS (
    SELECT userid 
    , courseid 
    , sessionid 
    , MIN(requestdate) 
    , MAX(requestdate) 
    , DATEDIFF(MINUTE, MIN(requestdate), MAX(requestdate)) 
    FROM PageLogSample 
    GROUP BY userid 
    , courseid 
    , sessionid 
) 
SELECT naive.userid 
, naive.sessioncount 
, naive.duration AS naiveduration 
, correction.duration AS correctionduration 
, naive.duration - ISNULL(correction.duration, 0) AS duration 
, CASE naive.duration - ISNULL(correction.duration, 0) 
    WHEN 10 THEN 'ok' 
    ELSE 'ERROR' 
END 
FROM (
    SELECT cte.userid 
    , COUNT(DISTINCT cte.sessionid) AS sessioncount 
    , SUM(cte.duration) AS duration 
    FROM cte 
    WHERE cte.courseid = @courseid 
    GROUP BY cte.userid 
) naive 
LEFT JOIN (
    SELECT errors.userid 
    , SUM(errors.duration) AS duration 
    FROM cte errors 
    WHERE errors.courseid <> @courseid 
    AND EXISTS (
     SELECT * 
     FROM cte 
     WHERE cte.start <= errors.start 
     AND cte.finish >= errors.finish 
     AND cte.courseid = @courseid 
    ) 
    GROUP BY errors.userid 
) correction 
ON naive.userid = correction.userid 
; 

-- userid sessioncount naiveduration correctionduration duration 
-- 1  1    10    NULL    10  ok 
-- 2  1    12    2     10  ok 
-- 3  1    12    NULL    12  ERROR 
-- 4  1    12    NULL    12  ERROR 
-- 5  2    10    NULL    10  ok 

更新: Ed Harpers commentは本当に私のアプローチを再考しました。

ここで3番目の試行があります。ここでは、どの行がコースへの入り口を表しているのか、誰がその行を残しているのかを最初に検索します。そして、私はすべての終わりの時間の合計を取って、すべての始まりの合計を引く。私はそれがより完璧ではないが、より正確だと思う。

DECLARE @courseid INT; 
SET @courseid = 1; 

WITH numberedcte (rn, id, userid, courseid, sessionid, requestdate) 
AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY sessionid, userid ORDER BY id) 
    , id 
    , userid 
    , courseid 
    , sessionid 
    , requestdate 
    FROM PageLogSample 
) 
, typedcte (rowtype, id, userid, courseid, sessionid, requestdate, nextrequestdate) 
AS (
    SELECT CASE 
     WHEN previousrequest.courseid = nextrequest.courseid 
      THEN 'between' 
     WHEN previousrequest.courseid IS NULL 
      OR nextrequest.courseid = numberedcte.courseid 
      THEN 'begin' 
     WHEN nextrequest.courseid IS NULL 
      OR previousrequest.courseid = numberedcte.courseid 
      THEN 'end' 
     ELSE 'error?' 
    END AS rowtype 
    , numberedcte.id 
    , numberedcte.userid 
    , numberedcte.courseid 
    , numberedcte.sessionid 
    , numberedcte.requestdate 
    , nextrequest.requestdate 
    FROM numberedcte 
    LEFT JOIN numberedcte previousrequest 
     ON previousrequest.userid = numberedcte.userid 
     AND previousrequest.sessionid = numberedcte.sessionid 
     AND previousrequest.rn = numberedcte.rn - 1 
    LEFT JOIN numberedcte nextrequest 
     ON nextrequest.userid = numberedcte.userid 
     AND nextrequest.sessionid = numberedcte.sessionid 
     AND nextrequest.rn = numberedcte.rn + 1 
    WHERE numberedcte.courseid = @courseid 
    AND (
     nextrequest.courseid = @courseid 
     OR previousrequest.courseid = @courseid 
    ) 
) 
, beginsum (userid, value) 
AS (
    SELECT userid, SUM(DATEPART(MINUTE, requestdate)) 
    FROM typedcte 
    WHERE rowtype = 'begin' 
    GROUP BY userid 
) 
, endsum (userid, value) 
AS (
    SELECT userid, SUM(DATEPART(MINUTE, ISNULL(nextrequestdate, requestdate))) 
    FROM typedcte 
    WHERE rowtype = 'end' 
    GROUP BY userid 
) 
SELECT beginsum.userid 
, endsum.value - beginsum.value AS duration 
FROM beginsum 
INNER JOIN endsum 
    ON beginsum.userid = endsum.userid 
; 

唯一の問題は、元のサンプルデータからユーザー1と5の出力が得られることです。追加されたユーザ6も正しい出力を与える。追加されたユーザ7は私に満足のいく出力を与える。ユーザー8はほぼ完璧です、私は最初の行から2番目に1分欠けています。

-- userid duration 
-- 1  10 
-- 5  10 
-- 6  10 
-- 7  9 
-- 8  9 

私はこれを完全に正しいものにすることはできません。行方不明の唯一の期間は、グループでは発生しなかったページ要求からのものです。誰かが孤独なページビューを取得する方法を見つけるのを助けることができますか?

更新: ここでは4番目の試行があります。ここで私は各リクエストに値を割り当て、それらを合計します。それは私が期待していた出力を私に厳密に与えるものではありませんが、十分に良いと思われるようです。

DECLARE @courseid INT; 
SET @courseid = 1; 

WITH numberedcte (rn, userid, courseid, sessionid, requestdate) 
AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY sessionid, userid ORDER BY id) 
    , userid 
    , courseid 
    , sessionid 
    , requestdate 
    FROM PageLogSample 
) 
, valuecte (value, userid, courseid, sessionid) 
AS (
    SELECT CASE 
     --alone 
     WHEN (previousrequest.courseid IS NULL 
      OR previousrequest.courseid <> numberedcte.courseid 
      ) 
      AND nextrequest.courseid <> numberedcte.courseid 
      THEN DATEDIFF(MINUTE, numberedcte.requestdate, nextrequest.requestdate) 
     --between 
     WHEN previousrequest.courseid = nextrequest.courseid 
      THEN 0 
     --begin 
     WHEN previousrequest.courseid IS NULL 
      OR nextrequest.courseid = numberedcte.courseid 
      THEN -1 * DATEPART(MINUTE, numberedcte.requestdate) 
     --ignored (end with no next request) 
     WHEN nextrequest.courseid IS NULL 
      AND previousrequest.courseid <> numberedcte.courseid 
      THEN 0 
     --end 
     WHEN nextrequest.courseid IS NULL 
      OR previousrequest.courseid = numberedcte.courseid 
      THEN DATEPART(MINUTE, ISNULL(nextrequest.requestdate, numberedcte.requestdate)) 
     --impossible? 
     ELSE 0 
    END 
    , numberedcte.userid 
    , numberedcte.courseid 
    , numberedcte.sessionid 
    FROM numberedcte 
    LEFT JOIN numberedcte previousrequest 
     ON previousrequest.userid = numberedcte.userid 
     AND previousrequest.sessionid = numberedcte.sessionid 
     AND previousrequest.rn = numberedcte.rn - 1 
    LEFT JOIN numberedcte nextrequest 
     ON nextrequest.userid = numberedcte.userid 
     AND nextrequest.sessionid = numberedcte.sessionid 
     AND nextrequest.rn = numberedcte.rn + 1 
    WHERE numberedcte.courseid = @courseid 
) 
SELECT userid 
, courseid 
, COUNT(DISTINCT sessionid) AS sessioncount 
, SUM(value) AS duration 
FROM valuecte 
GROUP BY userid 
, courseid 
ORDER BY userid 
; 

私が期待した結果ではありません。

-- userid courseid sessioncount duration 
-- 1  1   1    10 
-- 2  1   1    3 
-- 3  1   1    6 
-- 4  1   1    4 
-- 5  1   2    10 
-- 6  1   1    10 
-- 7  1   1    9 
-- 8  1   1    10 

実際のデータベースのローカルコピーでは、パフォーマンスは恐ろしいです。ですから、誰かがこれをより実践的な方法で書くようなアイデアを持っていれば...撮影してください。

更新: パフォーマンスがアップしています。私はインデックスを追加し、それは今、魅力を働かせます。

+2

問題を簡単に解決するためのスクリプトとサンプルの点では良い質問です。 – Andrew

+0

データの難しさは、requestdateに一貫した意味がないことです。コースの開始時間と終了時間が時々あります。 –

+0

素敵な質問に素敵なコメント。 –

答えて

0

さらに多くのサンプルデータと、各ユーザーが各コースに費やした時間の論理的な前提があります。

INSERT INTO PageLogSample (userid, courseid, sessionid, requestdate) 
-- [0, 10] = 10 minutes 
      SELECT 1, 1, 1, '00:00:00' 
UNION ALL SELECT 1, 1, 1, '00:10:00' 
-- [0, 3] = 3 minutes 
-- there is no way to know how long the user was on that last page 
UNION ALL SELECT 2, 1, 2, '00:00:00' 
UNION ALL SELECT 2, 2, 2, '00:03:00' 
UNION ALL SELECT 2, 2, 2, '00:05:00' 
UNION ALL SELECT 2, 1, 2, '00:12:00' 
-- [0, 3] + [12, 15] = 6 minutes 
-- the [5, 12] part was spent on a page of course 2 
UNION ALL SELECT 3, 1, 3, '00:00:00' 
UNION ALL SELECT 3, 2, 3, '00:03:00' 
UNION ALL SELECT 3, 2, 3, '00:05:00' 
UNION ALL SELECT 3, 1, 3, '00:12:00' 
UNION ALL SELECT 3, 2, 3, '00:15:00' 
-- [1, 3] + [13, 15] = 4 minutes 
UNION ALL SELECT 4, 2, 4, '00:00:00' 
UNION ALL SELECT 4, 1, 4, '00:01:00' 
UNION ALL SELECT 4, 2, 4, '00:03:00' 
UNION ALL SELECT 4, 2, 4, '00:05:00' 
UNION ALL SELECT 4, 1, 4, '00:13:00' 
UNION ALL SELECT 4, 2, 4, '00:15:00' 
-- [0, 5] + [10, 15] = 10 minutes 
UNION ALL SELECT 5, 1, 5, '00:00:00' 
UNION ALL SELECT 5, 1, 5, '00:05:00' 
UNION ALL SELECT 5, 1, 6, '00:10:00' 
UNION ALL SELECT 5, 1, 6, '00:15:00' 
-- [0, 10] = 10 minutes (ignoring everything inbetween) 
UNION ALL SELECT 6, 1, 7, '00:00:00' 
UNION ALL SELECT 6, 1, 7, '00:03:00' 
UNION ALL SELECT 6, 1, 7, '00:05:00' 
UNION ALL SELECT 6, 1, 7, '00:07:00' 
UNION ALL SELECT 6, 1, 7, '00:10:00' 
-- [0, 5] + [7, 11] = 9 minutes 
UNION ALL SELECT 7, 1, 8, '00:00:00' 
UNION ALL SELECT 7, 1, 8, '00:03:00' 
UNION ALL SELECT 7, 2, 8, '00:05:00' 
UNION ALL SELECT 7, 2, 8, '00:06:00' 
UNION ALL SELECT 7, 1, 8, '00:07:00' 
UNION ALL SELECT 7, 1, 8, '00:11:00' 
-- [0, 1] + [2, 4] + [5, 7] + [8, 13] = 10 
UNION ALL SELECT 8, 1, 9, '00:00:00' 
UNION ALL SELECT 8, 2, 9, '00:01:00' 
UNION ALL SELECT 8, 1, 9, '00:02:00' 
UNION ALL SELECT 8, 1, 9, '00:03:00' 
UNION ALL SELECT 8, 2, 9, '00:04:00' 
UNION ALL SELECT 8, 1, 9, '00:05:00' 
UNION ALL SELECT 8, 1, 9, '00:06:00' 
UNION ALL SELECT 8, 2, 9, '00:07:00' 
UNION ALL SELECT 8, 1, 9, '00:08:00' 
UNION ALL SELECT 8, 1, 9, '00:13:00' 
-- there is nothing we can say about either of there requests 
-- 0 minutes 
UNION ALL SELECT 9, 1, 10, '00:10:00' 
UNION ALL SELECT 9, 1, 11, '00:20:00' 
; 

今、私たちはこのように私たちのデータを取得:

WITH numberedcte (rn, userid, courseid, sessionid, requestdate) 
AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY sessionid, userid ORDER BY id) 
    , userid 
    , courseid 
    , sessionid 
    , requestdate 
    FROM PageLogSample 
) 
, valuecte (value, userid, courseid, sessionid) 
AS (
    SELECT CASE 
     --alone in session 
     WHEN previousrequest.courseid IS NULL 
      AND nextrequest.courseid IS NULL 
      THEN 0 
     --alone 
     WHEN (previousrequest.courseid IS NULL 
      OR previousrequest.courseid <> numberedcte.courseid 
      ) 
      AND nextrequest.courseid <> numberedcte.courseid 
      THEN DATEDIFF(MINUTE, numberedcte.requestdate, nextrequest.requestdate) 
     --between 
     WHEN previousrequest.courseid = nextrequest.courseid 
      THEN 0 
     --begin 
     WHEN previousrequest.courseid IS NULL 
      OR nextrequest.courseid = numberedcte.courseid 
      THEN -1 * DATEPART(MINUTE, numberedcte.requestdate) 
     --ignored (end with no next request) 
     WHEN nextrequest.courseid IS NULL 
      AND previousrequest.courseid <> numberedcte.courseid 
      THEN 0 
     --end 
     WHEN nextrequest.courseid IS NULL 
      OR previousrequest.courseid = numberedcte.courseid 
      THEN DATEPART(MINUTE, ISNULL(nextrequest.requestdate, numberedcte.requestdate)) 
     --impossible? 
     ELSE 0 
    END 
    , numberedcte.userid 
    , numberedcte.courseid 
    , numberedcte.sessionid 
    FROM numberedcte 
    LEFT JOIN numberedcte previousrequest 
     ON previousrequest.userid = numberedcte.userid 
     AND previousrequest.sessionid = numberedcte.sessionid 
     AND previousrequest.rn = numberedcte.rn - 1 
    LEFT JOIN numberedcte nextrequest 
     ON nextrequest.userid = numberedcte.userid 
     AND nextrequest.sessionid = numberedcte.sessionid 
     AND nextrequest.rn = numberedcte.rn + 1 
    WHERE numberedcte.courseid = @courseid 
) 
SELECT userid 
, courseid 
, COUNT(DISTINCT sessionid) AS sessioncount 
, SUM(value) AS duration 
FROM valuecte 
GROUP BY userid 
, courseid 
ORDER BY userid 
; 

これは私が得る結果です。私はそれにとても満足しています。セッション数がユーザー9にどのように残っているかに注目してください。

userid courseid sessioncount duration 
1  1   1    10 
2  1   1    3 
3  1   1    6 
4  1   1    4 
5  1   2    10 
6  1   1    10 
7  1   1    9 
8  1   1    10 
9  1   2    0 
0

申し訳ありませんが、データに問題があると思います。提供されたサンプルデータを見ると、ユーザー2はcourseid 1に12分、courseid 2に2分あります。

正しいデータを入力してもよろしいですか?

+0

データは正しいですが、関連する意味を得るのは難しいです。ユーザー2はコース1でスタートし、コース2に2分間行き、その後コース1に戻ります。コース1(10分)に費やした時間が必要です。したがって、彼が別のコースで過ごした2分を差し引いた12分。 –

+0

あなたは正しいと思われます。データの私の元の解釈に欠陥がありました。 –

0

これは私が得るほど近いです。ユーザーID 4では失敗します。

私のコメントで述べたように、requestdateは時にはコースの始まりと終わりになることがありますが、特定の行でどの役割を果たしているかを導き出すための簡単な一般的なルールはありません。

DECLARE @courseid INT; 
SET @courseid = 1; 

WITH orderCTE 
AS 
(
     SELECT * 

       ,ROW_NUMBER() OVER (PARTITION BY sessionid 
            ORDER BY id 
           ) AS rn 
     FROM PageLogSample 
     --order by rn 
) 
,startendCTE 
AS 
(
     SELECT CASE WHEN start1.rn = 1 
        THEN start1.courseid 
        ELSE end1.courseid 
       END courseid 
       ,start1.sessionid 
       ,start1.userid 
       ,DATEDIFF(mi,start1.requestdate,end1.requestdate) duration 
     FROM orderCTE AS start1 
     JOIN orderCTE AS end1 
     ON end1.rn = start1.rn + 1 
     AND end1.sessionid = start1.sessionid 
) 
SELECT courseid 
     ,COUNT(1) sessionCount 
     ,userid 
     ,SUM(duration) totalDuration 
FROM startendCTE 
WHERE courseid = @courseid 
GROUP BY courseid 
     ,userid; 
+0

私は始めと終わりの行を最初に探すという考えが好きです。あなたは私に新しいアプローチをとるよう促しました。 –

0

これはかなり厄介ですが、あなたがそれをテストすることをお勧めしますので、私は、他のコースとそれをしようとしなかったCourseID 1のために働いているように見えます! :D

基本的な前提は、私​​が目標CourseIDの最初と最後のセッションの間の時間を得ていることです、そして、私は指定されたCourseIDではないセッションの期間を差し引いていますが、セッション要求時間は、目標CourseIDの最小および最大要求時間内に収まった。私はそれが理にかなったことを願う

クエリーは、CTEなどで間違いなくクリーンアップできました。面白い質問BTW! :)

DECLARE @courseid INT; 
SET @courseid = 1; 

SELECT 
    TargetCourse.UserID, 
    COUNT(Distinct(TargetCourse.SessionID)) as SessionCount, 
    SUM(TargetCourse.Duration - Coalesce(OtherCourses.Duration,0)) as Duration 
FROM 
(
    SELECT 
     TargetCourse.UserID, TargetCourse.SessionID, 
     MIN(TargetCourse.RequestDate) FirstRequest, MAX(TargetCourse.RequestDate) LastRequest, 
     DATEDIFF(MINUTE, MIN(TargetCourse.RequestDate), MAX(TargetCourse.RequestDate)) AS duration 
    FROM 
     PageLogSample TargetCourse 
    WHERE 
     TargetCourse.CourseID = @courseid 
    GROUP BY 
     TargetCourse.UserID, TargetCourse.SessionID  
) as TargetCourse 
LEFT OUTER JOIN 
(
    SELECT 
     OtherCourses.UserID, OtherCourses.SessionID, 
     MIN(OtherCourses.RequestDate) AS FirstRequest, MAX(OtherCourses.RequestDate) AS LastRequest, 
     DATEDIFF(MINUTE, MIN(OtherCourses.RequestDate), MAX(OtherCourses.RequestDate)) AS duration 
    FROM 
     PageLogSample OtherCourses 
    WHERE 
     OtherCourses.CourseID <> @courseid AND 
     OtherCourses.RequestDate between 
      (Select MIN(RequestDate) From PageLogSample T Where T.UserID = OtherCourses.UserID and T.CourseID = @courseid) AND 
      (Select MAX(RequestDate) From PageLogSample T Where T.UserID = OtherCourses.UserID and T.CourseID = @courseid) 
    GROUP BY 
     OtherCourses.UserID, OtherCourses.SessionID 
) as OtherCourses ON 
OtherCourses.UserID = TargetCourse.UserID AND 
OtherCourses.FirstRequest BETWEEN TargetCourse.FirstRequest and TargetCourse.LastRequest 
Group By TargetCourse.UserID 
+0

非常に良いですが、まだ完璧ではありません。減算する時間を検索するときには、いくつかのcourseidに複数の「ギャップ」が存在する可能性があることに留意する必要があります。これを示すためにサンプルデータに余分なユーザーを追加しました。 –

+0

ああ、それを指摘してくれてありがとう。追加のユーザーを追加して別のユーザーに公開します。 :) – WesleyJohnson

-1

"データは正しいですが、関連する意味を取得するのは難しいです。"

私はこのことを言葉の矛盾に対応するように押さえています。それが何を意味するのかわからないデータはデータではありません。あなたの元の質問については

:あなたが必要なもの

はINTERVAL型のためのまともなサポートを提供していますDBMSです。そのリーグではSQLシステムは使用されていません。いくつかのチュートリアルシステムとは別に、私自身のDBMS(この文脈ではこれ以上プッシュしないので、リンクはありません)は、私が知っている唯一のものです。

興味のある方は、「インターバルタイプ」、「通常のフォームをパック」、「一時的なデータ」についてgoogleで調べてみてください。

関連する問題