2

特定のクラスに出席したか欠席したかを示す生徒のリストがあります。

    CREATE TABLE classlist
        (`id` int, `studentid` int, `subjectid` int, `presentid` int)
    ;

    CREATE TABLE student
        (`id` int, `name` varchar(4))
    ;

    CREATE TABLE subject
        (`id` int, `name` varchar(4))
    ;

    CREATE TABLE classStatus
        (`id` int, `name` varchar(8))
    ;

    INSERT INTO classlist
        (`id`, `studentid`, `subjectid`, `presentid`)
    VALUES
        (1, 111, 1, 1),
        (2, 222, 3, 0),
        (3, 333, 2, 1),
        (4, 111, 4, 0),
        (5, 111, 1, 1),
        (6, 222, 3, 0),
        (7, 333, 2, 1),
        (8, 111, 4, 0),
        (9, 111, 4, 0),
        (10, 111, 4, 0),
        (11, 111, 1, 1),
        (12, 333, 3, 1),
        (13, 333, 2, 1),
        (14, 333, 3, 1)
    ;

    INSERT INTO student
        (`id`, `name`)
    VALUES
    (111, 'John'),
    (222, 'Kate'),
    (333, 'Matt')
    ;

    INSERT INTO subject
        (`id`, `name`)
    VALUES
    (1, 'MATH'),
    (2, 'ENG'),
    (3, 'SCI'),
    (4, 'GEO')
    ;

    INSERT INTO classStatus
        (`id`, `name`)
    VALUES
    (0, 'Absent'),
    (1, 'Present')
    ;

Fiddlehttp ://sqlfiddle.com/#!2/a2d93/5を参照してください

誰が不在で、全体的に次のようなものを提示しているのかを数えることができます。

    SELECT
       studentid,
       students.name AS NAME,
       SUM(presentid = 1) AS present,
       SUM(presentid = 0) AS absent

    FROM classlist
    INNER JOIN student as students ON classlist.studentid=students.id

     GROUP BY studentid, NAME

しかし、生徒が連続して何回クラスに出席/欠席したかを知りたいので、教師は誰かが多くの時間を欠席したか、誰かが良い出席に対して報われるかなどを簡単に確認できます。縞模様ですが、データが私に提示された方法と一致するものはないようですので、これを達成する方法がわかりませんか?

以下の私のサンプルデータに基づいて明確にするために、ストリークの出力は次のようになります。

        (1, 111, 1, 1), /* John Present 1 times in a row */
        (2, 222, 3, 0), /* Kate Absent 1 times in a row */
        (3, 333, 2, 1), /* Matt Present 1 times in a row */
        (4, 111, 4, 0), /* John Absent 1 times in a row */
        (5, 111, 1, 1), /* John Present 1 times in a row */
        (6, 222, 3, 0), /* Kate Absent 2 times in a row */
        (7, 333, 2, 1), /* Matt Present 2 times in a row */
        (8, 111, 4, 0), /* John Absent 1 times in a row */
        (9, 111, 4, 0), /* John Absent 2 times in a row */
        (10, 111, 4, 0), /* John Absent 2 times in a row */
        (11, 111, 1, 1), /* John Present 1 times in a row */
        (12, 333, 3, 1), /* Matt Present 3 times in a row */
        (13, 333, 2, 1), /* Matt Present 4 times in a row */
        (14, 333, 3, 1) /* Matt Present 5 times in a row */
        /*Showing the latest status for each user*/
        /* John Present 1 times in a row */
        /* Kate Absent 2 times in a row */
        /* Matt Present 5 times in a row */

ジョンプレゼント1。

ケイト不在2。

マットプレゼント5。

4

5 に答える 5

3

これにより、最後の行と同じ値を持つ連続した行の数が得られます。

select
  classlist.studentid,
  student.name,
  classStatus.name status,
  count(*) presentcnt
from
  classlist inner join student
  on classlist.studentid=student.id
  inner join classstatus
  on classlist.presentid=classstatus.id
  inner join (
    select
      studentid,
      max(case when presentid=0 then id end)  max_0,
      max(case when presentid=1 then id end)  max_1
    from classlist
    group by studentid
  ) s
  on coalesce(classlist.id>least(max_0,max_1) and
       classlist.id<=greatest(max_0,max_1),1)
  and s.studentid=classlist.studentid
group by classlist.studentid

サブクエリで、presentid = 0 の最大 ID と presentid = 1 の最大 ID を抽出しています。

外側のクエリでは、id が max_0 と max_1 の最小値よりも大きく、これら 2 つの最大値よりも小さいすべての行を抽出してカウントしています。最後の値が何であれ、これらは最後の値と同じ値を持つすべての行です。

またはのいずれmax_0max_1が null の場合、すべての行に 1 または 0 の 1 つの値しかないことを意味し、それらすべてを取得する必要があります。max_0 または max_1 のいずれかが null の場合、条件全体も null になります。) を使用Coalesce( condition, 1して、その場合はすべての行を返します。

いくつかの非集計列でグループ化して表示していることに注意してくださいclasslist.studentid。ただし、非集計列はすべて同じ値を持つため、これは許可されている状況です。

于 2013-01-11T01:01:00.160 に答える
1

idfromclasslistを注文に使用できる場合、期待される結果が得られます

SELECT 
  s.name,
  CASE t1.presentid
    WHEN 0 THEN 'absent'
    WHEN 1 THEN 'present'
  END state,
  t1.pc  
FROM (
  SELECT
    c.id,
    c.studentid,
    c.presentid,
    @pcount := IF( @pid = presentid AND @sid = studentid, @pcount + 1, 1 ) as pc,
    @pid := presentid,
    @sid := studentid
  FROM
    classlist c
  ORDER BY
    studentid, id ) t1
  JOIN student s 
    ON t1.studentid = s.id
WHERE
  ( t1.studentid, t1.id ) IN ( SELECT 
                                 studentid, 
                                 MAX( id ) 
                               FROM classlist 
                               GROUP BY studentid );

SQL フィドルのデモ

于 2013-01-10T22:31:17.413 に答える
1

これを試して:

SELECT A.studentid, s.name, IF(presentid = 1,  'present', 'absent') STATUS, 
       ABS(SUM(IF(presentid = 1, 1, -1))) AS presentcnt
FROM classlist A 
INNER JOIN student s ON A.studentid = s.id 
LEFT JOIN (SELECT MAX(id) id, studentid 
           FROM classlist GROUP BY studentid
          ) B ON A.studentid = B.studentid AND A.id = B.id 
GROUP BY A.studentid

このSQL FIDDLE DEMOをチェックしてください

出力

| STUDENTID | NAME |  STATUS | PRESENTCNT |
-------------------------------------------
|       111 | John | present |          1 |
|       222 | Kate |  absent |          2 |
|       333 | Matt | present |          5 |
于 2013-01-07T09:47:06.483 に答える
1

これが欲しいですか?:

SELECT
   studentid,
   name,
   SUM(present = 1) AS present,
   SUM(present = 0) AS absent,
   count(subject) as classTimes,
   subject
   FROM your_table GROUP BY studentid, name,subject
于 2013-01-07T08:42:12.127 に答える
0

あなたの質問の何点かわかりません。これが必要な場合

ジョンプレゼント1。

ケイト不在2。

マットプレゼント5。

Uはこれを試すかもしれません:

SELECT
   studentid,
   students.name AS NAME,
   SUM(presentid = 1) AS present,
   SUM(presentid = 0) AS absent,
   IF( SUM(presentid = 1)-SUM(presentid = 0)>=0,SUM(presentid = 1)-SUM(presentid = 0),SUM(presentid = 0)-SUM(presentid = 1)) AS aliase
FROM classlist
  INNER JOIN student as students ON classlist.studentid=students.id
GROUP BY studentid, NAME
于 2013-01-07T10:04:29.840 に答える