1

まず第一に:タイトルは申し訳ありませんが、後でもっと良いものを見つけるかもしれません。

数分前に聞いたのですが、何が欲しいのか説明できなかったので、もう一度やってみます:)

これが私のテーブル構造です: http ://sqlfiddle.com/#!2 / b25f9 / 37

このテーブルは、ユーザーセッションを保存するために使用されます。

この中から、アクティブユーザーの数を示す積み上げ棒グラフを生成したいと思います。私の考えは、このように最後の日のオンライン時間に基づいてユーザーをグループ化することでした ここに画像の説明を入力してください

その金曜日を言いましょう:

  • グループB:木曜日(および今日)オンラインだったユーザー
  • グループC:木曜日ではなく水曜日(および今日)にオンラインでなかったユーザー
  • グループD:木曜日または水曜日ではなく火曜日(および今日)にオンラインであったユーザー
  • グループE:木曜日、水曜日、火曜日ではなく、先週の月曜日、日曜日、土曜日(および今日)にオンラインでなかったユーザー
  • グループA:他のグループと一致しないユーザー(ただし、今日のみ)

  • それらのグループのユーザー数(特定の日)のみを知りたい

  • ユーザーは、これらのグループの1つにのみ参加できます(同じ日)
4

6 に答える 6

2

別の更新:偶然(コピー&ペーストによる)がありましstarttime = ... or starttime = ...たが、starttime = ... or endtime = ...

アップデート:

私のクエリをより詳細に説明するには(最後のクエリにはさらに多くのコメントがあります):

最初に私たちは単に得ました

SELECT
...
FROM gc_sessions s
WHERE DATE(starttime) = CURDATE() OR DATE(endtime) = CURDATE()

これは、「セッションが今日開始または終了したすべてのユーザーを教えてください」と言っているようなものではありません。これらを何度も何度も検討する必要があるため、クエリは少し不器用になりますが、実際にはそれほど複雑ではありません。

したがって、通常はCOUNT()関数を使用して何かをカウントしますが、「条件付きカウント」が必要なため、SUM()関数を使用して、1を追加する場合と追加しない場合を指定します。

SUM (CASE WHEN ... THEN 1 ELSE 0 END) AS a_column_name

SUM()関数は、今日からのセッションの結果セットの各行を調べます。したがって、この結果セットの各ユーザーについて、指定した日付にこのユーザーがオンラインであったかどうかを確認します。彼/彼女が何回オンラインであったかは関係ないので、パフォーマンス上の理由から、を使用しますEXISTS。を使用EXISTSすると、何かが見つかるとすぐに停止するサブクエリを指定できるため、何かが見つかったときに何が返されるかは、そうでない限り重要ではありませんNULL。だから私が選んだ理由を混乱させないでください1。サブクエリでは、現在外部クエリから検査されているユーザーを内部クエリ(サブクエリ)のユーザーに接続し、時間枠を指定する必要があります。前に説明したように、すべての基準がカウント1を満たしている場合、それ以外の場合は0です。

SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndYesterday,

次に、条件と出来上がりごとに列を作成します。1つのクエリで必要なものがすべて揃っています。したがって、更新された質問で基準が変更されたので、ルールを追加する必要があります。

SELECT
/*this is like before*/
SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS FridayAndThursday,
SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 2 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 2 DAY)))
         /*this one here is a new addition, since you don't want to count the users that were online yesterday*/
         AND NOT EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) = CURDATE() - INTERVAL 1 DAY)))
    THEN 1 ELSE 0 END) AS FridayAndWednesdayButNotThursday,
SUM(CASE WHEN 
         EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) = CURDATE() - INTERVAL 3 DAY) /* minus 3 days to get tuesday*/
                       OR (date(endtime) = CURDATE() - INTERVAL 3 DAY)))
         /*this is the same as before, we check again that the user was not online between today and tuesday, but this time we really use BETWEEN for convenience*/
         AND NOT EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                  AND ((date(starttime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY) 
                       OR (date(endtime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY)))
    THEN 1 ELSE 0 END) AS FridayAndTuesdayButNotThursdayAndNotWednesday,
.../*and so on*/
FROM gc_sessions s
WHERE DATE(starttime) = CURDATE() OR DATE(endtime) = CURDATE()

だから、私はあなたが今アイデアを得ることを願っています。他に質問は?お気軽にお尋ねください。

更新の終わり

以前のバージョンの質問への回答:

select 
SUM(CASE WHEN EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                      AND ((date(starttime) = CURDATE() - INTERVAL 1 DAY) 
                           OR (date(starttime) = CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndYesterday,
SUM(CASE WHEN EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                      AND ((date(starttime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY) 
                           OR (date(starttime) BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndYesterdayOrTheDayBeforeYesterday,
SUM(CASE WHEN EXISTS (SELECT 1 FROM gc_sessions sub_s WHERE s.user = sub_s.user 
                      AND ((date(starttime) BETWEEN CURDATE() - INTERVAL 7 DAY AND CURDATE() - INTERVAL 1 DAY) 
                           OR (date(starttime) BETWEEN CURDATE() - INTERVAL 7 DAY AND CURDATE() - INTERVAL 1 DAY))) 
    THEN 1 ELSE 0 END) AS todayAndWithinTheLastWeek
from gc_sessions s
where date(starttime) = CURDATE()
or date(endtime) = CURDATE()
于 2013-01-28T12:21:02.517 に答える
1

セッションテーブルに依存する代わりに、dateとuser_idの2つのフィールドを格納する別のテーブルを作成することをお勧めします。ユーザーがログインするたびに、このテーブルに新しいエントリを挿入する必要があります。

このようにして、3つの要件すべてを取得できるようになります。

于 2013-01-28T12:00:56.653 に答える
1

表の例:

CREATE TABLE `test`.`user_login_history` (
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `userid` INTEGER UNSIGNED NOT NULL,
  `date` DATETIME NOT NULL,
  PRIMARY KEY (`id`)
)
ENGINE = InnoDB;

ユーザーがログインしたら、そのユーザーが今日ログインしているかどうかを確認します。

select count(*) from user_login_history where 
userid = 1 and `date` = '2013-01-28 00:00:00';

戻り値が1の場合、彼/彼女は今日ログインしていることを意味します。変更は必要ありません。
ただし、戻り値が0の場合は、今日ログインしていないことを意味します。だからそれを記録しなさい。

insert into user_login_history(userid,`date`)values(1,'2013-01-28 00:00:00');

Q1。今日オンラインで、昨日もオンラインだったユーザーは何人いますか?

select count(*) from user_login_history u where 
u.`date` = '2013-01-28 00:00:00' and 
(
select count(*) from user_login_history v where 
v.`date` = '2013-01-27 00:00:00' and 
v.userid = u.userid
) = 1;

Q2。過去2日間にオンラインであったユーザーの数

select count(*) from user_login_history u where 
u.`date` = '2013-01-28 00:00:00' and
(
select count(*) from user_login_history v where
v.`date` >= '2013-01-26 00:00:00' and
v.`date` <= '2013-01-27 00:00:00' and
v.userid = u.userid
) > 0;

Q3。過去7日間にオンラインであった、今日オンラインであったユーザーの数

select count(*) from user_login_history u where 
u.`date` = '2013-01-28 00:00:00' and
(
select count(*) from user_login_history v where
v.`date` >= '2013-01-21 00:00:00' and
v.`date` <= '2013-01-27 00:00:00' and
v.userid = u.userid
) > 0;
于 2013-01-28T12:31:21.507 に答える
0
     SELECT today.user
          , GROUP_CONCAT(DISTINCT today.ip) ip
       FROM gc_sessions today
       JOIN gc_sessions yesterday
         ON DATE(yesterday.starttime) = DATE(today.starttime) - INTERVAL 1 DAY
        AND today.user = yesterday.user
      WHERE DATE(today.starttime) = '2013-01-10'
      GROUP 
         BY today.user;
于 2013-01-28T12:35:31.007 に答える
0

昨日は

select id from gc_sessions where id in 
( 
  select id 
  from gc_sessions 
  where starttime > subdate(current_date, 2)
  and endtime < subdate(current_date, 1)
)

and starttime > subdate(current_date, 1);

2日間

select id from gc_sessions where id in 
( 
  select id 
  from gc_sessions 
  where starttime > subdate(current_date, 3)
  and endtime < subdate(current_date, 1)
)

and starttime > subdate(current_date, 1);

7日間

select id from gc_sessions where id in 
( 
  select id 
  from gc_sessions 
  where starttime > subdate(current_date, 8)
  and endtime < subdate(current_date, 1)
)

and starttime > subdate(current_date, 1);
于 2013-01-28T12:01:32.330 に答える
0

指定された範囲(たとえば、1日/2日/7日)からデータをロードし、それを当日のデータと比較するサブクエリを追加する必要があります。

set @range = 7;
select * from gc_sessions
WHERE user in (SELECT user from gc_sessions
where starttime between subdate(current_date, @range) AND subdate(current_date, 1))

AND starttime > subdate(current_date, 0)

@range日数に関する情報はどこにありますか。拡張されたSQLフィドルを-http://sqlfiddle.com/#!2/9584b/24で参照してください

于 2013-01-28T12:20:14.793 に答える