4

ペディ紙のようなものを作ろうとしています。そのために、次のテーブルがあります。

チーム

CREATE TABLE `teams` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `creator_id` int(11) NOT NULL,
  `friend_id` int(11) DEFAULT NULL,
  `team_name` varchar(128) NOT NULL,
  PRIMARY KEY (`id`)
);

team_log

CREATE TABLE IF NOT EXISTS `progress_tracker` (
  `id` int(8) NOT NULL AUTO_INCREMENT,
  `user_id` int(8) NOT NULL,
  `team_id` int(11) NOT NULL,
  `date` date NOT NULL,
  `clues_found` int(11) NOT NULL,
  `clues_to_find` int(11) NOT NULL,
  PRIMARY KEY (`id`)
);
  1. 各チームは 2 人のユーザーで構成されています。
  2. 各ユーザーは、見つかったさまざまな数の手がかりから始めます。
  3. clues_found は増加または減少する可能性があります。最大数が最新であるという保証はありません。

ユーザーが参加してから見つけた手がかりの数の平均に基づいて、チームのランク (パーセンテージ) を取得する必要があります (チーム内の両方のユーザーについて)。最低日)。

たとえば、各テーブルに次のデータがあるとします。

チームテーブルデータ

+--------+------------+------------+---------------+
|     id | creator_id | friend_id  |   team_name   |
+--------+------------+------------+---------------+
|      1 |         25 |         28 |         Test1 |
|      2 |         31 |          5 |         Test2 |
+--------+------------+------------+---------------+

team_log テーブル データ

+--------+---------+---------+------------+-------------+---------------+
|     id | user_id | team_id |    date    | clues_found | clues_to_find |
+--------+---------+---------+------------+-------------+---------------+
|      1 |      25 |       1 | 2013-01-6  |           3 |            24 |
|      2 |      25 |       1 | 2013-01-8  |           7 |            24 |
|      3 |      25 |       1 | 2013-01-10 |          10 |            24 |
|      4 |      28 |       1 | 2013-01-8  |           5 |            30 |
|      5 |      28 |       1 | 2013-01-14 |          20 |            30 |
|      6 |      31 |       2 | 2013-01-11 |           6 |            14 |
|      7 |       5 |       2 | 2013-01-9  |           2 |            20 |
|      8 |       5 |       2 | 2013-01-10 |          10 |            20 |
|      9 |       5 |       2 | 2013-01-12 |          14 |            20 |
+--------+---------+---------+------------+-------------+---------------+

望ましい結果

+-------------+---------------------+
|     team_id |   team_percentage   |
+-------------+---------------------+
|           1 |         39,58333333 |
|           2 |         30          |
+-------------+---------------------+

参考までに、これは理解に役立つ中間表現です。

+-------------+---------+---------------------+
|     user_id | team_id | precentage_per_user |
+-------------+---------+---------------------+
|          25 |       1 | 29,16666667         |
|          28 |       1 | 50                  |
|          31 |       2 | 0                   |
|           5 |       2 | 60                  |
+-------------+---------+---------------------+

これまでのところ、次のSQLがあります。

SELECT STRAIGHT_JOIN
      tl2.team_id, (tl2.weight - tl1.weight)*100/tl2.clues_to_find
   from 
       ( select
               team_id,user_id,clues_found
            FROM 
               `team_log` 
            where 1

            group by
               team_id, user_id
            order by
               `date` ) base
       join (select team_id, user_id, clues_found, clues_to_find from `team_log` where user_id = base.user_id and team_id = base.team_id group by team_id, user_id order by `date` desc) tl2

しかし、2 番目のクエリ内で base.user_id を使用することは許可されていないため、これはエラーを返します。また、自分が正しい方向に向かっているかどうかもよくわかりません。

誰でも助けてもらえますか?

4

4 に答える 4

2

正しい結果を生成する別のクエリは次のとおりです。

SELECT calc.team_id, AVG((calc.end_clues - calc.start_clues)/calc.total_clues*100) as team_percentage
FROM
    (SELECT log1.user_id, log1.team_id, log1.clues_found as start_clues, log2.clues_found as end_clues, log2.clues_to_find as total_clues FROM team_log log1
    JOIN
    (SELECT MIN(id) as start_id, MAX(id) as end_id FROM team_log GROUP BY user_id) ids
    ON ids.start_id = log1.id
    JOIN team_log log2 ON ids.end_id = log2.id) calc
GROUP BY team_id
ORDER BY team_id;

そしてSQLフィドル-リンク...

于 2013-01-14T20:52:16.280 に答える
1

これは少し醜いですが、うまくいくはずです:

select
   team_id,
   AVG(percentage_per_user) as team_percentage
from (select
  team_id,
  user_id,
  ((select clues_found from progress_tracker as x
      where x.user_id = m.user_id order by x.date desc limit 0, 1)
    - (select clues_found from progress_tracker as y
      where y.user_id = m.user_id order by y.date asc limit 0, 1))
  / MAX(clues_to_find)
  as percentage_per_user
from progress_tracker as m
group by team_id, user_id
) as userScore
group by team_id
order by team_percentage desc;

内部クエリを単独で実行すると、中間の「ユーザーごと」の結果が得られることに注意してください。

于 2013-01-14T20:32:54.790 に答える
1

これを見てコメントしてください:

チームの割合:

select z.team_id, avg(z.pct) as teampct
from (
select x.user_id, y.team_id, x.mndate,
y.mxdate, x.mnclues_found,
y.mxclues_found, 
(((y.mxclues_found - x.mnclues_found)*100)
/y.mxclues_tofind) pct
from 
(select user_id, team_id, min(date) mndate, 
min(clues_found) as mnclues_found
from team_log
group by user_id, team_id) x
left join 
(select user_id, team_id, max(date) mxdate, 
max(clues_found) as mxclues_found, 
 max(clues_to_find) as mxclues_tofind
from team_log
group by user_id, team_id) y
on x.user_id = y.user_id and
x.team_id = y.team_id) z
group by z.team_id
;

結果 1:

| USER_ID | TEAM_ID |   MNDATE |   MXDATE | MNCLUES_FOUND | MXCLUES_FOUND |     PCT |
-------------------------------------------------------------------------------------
|       5 |       2 | 13-01-09 | 13-01-12 |             2 |            14 |      60 |
|      25 |       1 | 13-01-06 | 13-01-10 |             3 |            10 | 29.1667 |
|      28 |       1 | 13-01-08 | 13-01-14 |             5 |            20 |      50 |
|      31 |       2 | 13-01-11 | 13-01-11 |             6 |             6 |       0 |

最終結果:

| TEAM_ID |  TEAMPCT |
----------------------
|       1 | 39.58335 |
|       2 |       30 |
于 2013-01-14T20:30:30.410 に答える
1

SQLフィドル

SELECT `team_id`,
  (SUM(CASE WHEN b.`date` IS NULL THEN 0 ELSE `clues_found` * 100 / `clues_to_find` END) -
  SUM(CASE WHEN c.`date` IS NULL THEN 0 ELSE `clues_found` * 100 / `clues_to_find` END)) / 2
FROM `team_log` a
  LEFT JOIN (
    SELECT `team_id`, `user_id`, MAX(date) AS `date`
    FROM `team_log`
    GROUP BY `team_id`, `user_id`) b
  USING (`team_id`, `user_id`, `date`)
  LEFT JOIN (
    SELECT `team_id`, `user_id`, MIN(date) AS `date`
    FROM `team_log`
    GROUP BY `team_id`, `user_id`) c
  USING (`team_id`, `user_id`, `date`)
  GROUP BY `team_id`

あなたは常に 2 人のチーム メンバーがいると言うので、私は を使用しまし/2た。可変サイズのチームの場合は、少し複雑になります。

于 2013-01-14T19:49:47.043 に答える