0

登録ユーザーだけが動画を視聴できるイントラネット サイトを持っています。ユーザーは、iPhone、iPad、Android、Web などの複数のプラットフォームで動画を視聴できます。私はそれらすべての情報を追跡しています (問題を単純化するために、他のプラットフォームは考慮しないでください)。管理パネルでいくつかのビデオ視聴レポートを表示しようとしています。

テーブル構造は以下のとおりです (他にもたくさんの列がありますが、この問題には重要ではありません)。

CREATE TABLE IF NOT EXISTS `history` (
  `history_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `video_id` int(11) unsigned NOT NULL,
  `user_id` int(11) unsigned NOT NULL,
  `platform_id` int(11) unsigned NOT NULL,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`history_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=9 ;

INSERT INTO `history` (`history_id`, `video_id`, `user_id`, `platform_id`, `created`) VALUES
(1, 1, 1, 1, '2012-05-06 08:13:57'),
(2, 2, 1, 1, '2012-05-06 13:23:57'),
(3, 1, 1, 4, '2012-05-06 18:16:39'),
(4, 4, 2, 3, '2012-05-07 08:14:19'),
(5, 1, 2, 3, '2012-05-07 08:14:55'),
(6, 2, 1, 1, '2012-05-07 15:14:55'),
(7, 3, 2, 1, '2012-05-07 18:05:14'),
(8, 3, 1, 4, '2012-05-07 18:15:24');

CREATE TABLE IF NOT EXISTS `sys_list_of_values` (
  `value_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `display_text` text COLLATE utf8_unicode_ci NOT NULL,
  `list_value` text COLLATE utf8_unicode_ci NOT NULL,
  `list_group` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`value_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=10 ;

INSERT INTO `sys_list_of_values` (`value_id`, `display_text`, `list_value`, `list_group`) VALUES
(1, 'iPhone', 'iphone', 'platform'),
(2, 'Android', 'android', 'platform'),
(3, 'iPad', 'ipad', 'platform'),
(4, 'Website', 'web', 'platform'),
(5, 'Active', 'active', 'status'),
(6, 'Passive', 'passive', 'status'),
(7, 'Waiting for approvement', 'waiting', 'status'),
(8, 'Spam', 'spam', 'status'),
(9, 'Deleted', 'deleted', 'status');

CREATE TABLE IF NOT EXISTS `users` (
  `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(80) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;

INSERT INTO `users` (`user_id`, `username`) VALUES
(1, 'test_user_1'),
(2, 'test_user_2');

CREATE TABLE IF NOT EXISTS `videos` (
  `video_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(11) unsigned NOT NULL,
  `title` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `status` int(11) unsigned NOT NULL,
  PRIMARY KEY (`video_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=5 ;

INSERT INTO `videos` (`video_id`, `user_id`, `title`, `created`, `status`) VALUES
(1, 1, 'Test Video 1', '2012-05-07 08:12:52', 7),
(2, 1, 'Test Video 2', '2012-05-07 08:12:52', 5),
(3, 1, 'Test Video 3', '2012-05-07 08:13:17', 5),
(4, 1, 'Test Video 4', '2012-05-07 08:13:17', 6);

以下のようなレポートを表示しようとしています。

Platform      |     Watch_Count
===============================
iPhone                  20
iPad                     0
Android                  2
Website                120
Total                  142

、などvideo_idのフィルター オプションがいくつかあります。すべての動画、特定の動画 (video_id)、または日付間 (created) などの合計視聴レポートを表示したいと考えています。また、プラットフォームが 0 であるかどうかにかかわらず、すべてのプラットフォームを表示したいと考えています。createdplatform

次のクエリは iPhone と Web サイトのみを表示しますが、すべてのプラットフォームを表示したいと考えています。ウォッチ カウントがない場合は、0 (ゼロ) として表示する必要があります。watch_countまた、すべての sを合計して合計を表示する最終行を表示することもできません。

SELECT sys_list_of_values.display_text, COUNT(history.history_id) AS 'total_watch' FROM history
JOIN sys_list_of_values ON sys_list_of_values.value_id = history.platform_id
WHERE history.video_id = 1
AND history.created <  '2012-05-07'
GROUP BY history.platform_id
4

4 に答える 4

3

を保持し、にFROM HISTORY変更JOINRIGHT JOIN

SELECT sys_list_of_values.display_text, COUNT(history.history_id) AS 'total_watch' 
FROM history
RIGHT JOIN sys_list_of_values 
   ON sys_list_of_values.value_id = history.platform_id
   AND history.created <  '2012-05-07'
   AND history.video_id = 1

GROUP BY sys_list_of_values.value_id 
order by sys_list_of_values.display_text;

を使用する場合はLEFT JOIN、history と sys_list_of_values の場所を切り替えます。

SELECT sys_list_of_values.display_text, COUNT(history.history_id) AS 'total_watch' 
FROM sys_list_of_values 
LEFT JOIN history
   ON sys_list_of_values.value_id = history.platform_id
   AND history.created <  '2012-05-07'
   AND history.video_id = 1

GROUP BY sys_list_of_values.value_id 
order by sys_list_of_values.display_text;

ライブ テスト: http://www.sqlfiddle.com/#!2/495d1/15


ROLLUP を使用した GROUP BY は ORDER と互換性がありません。ROLLUP は自動的にリストをソートしますが、ORDER を削除するだけです。

SELECT sys_list_of_values.display_text, 
  -- sys_list_of_values.value_id,
  COUNT(history.platform_id) AS 'total_watch' 
FROM sys_list_of_values 
LEFT JOIN history
   ON sys_list_of_values.value_id = history.platform_id
   AND history.created <  '2012-05-07'
   AND history.video_id = 1

where sys_list_of_values.list_group = 'platform'
GROUP BY 
 sys_list_of_values.display_text with rollup

ライブ テスト: http://www.sqlfiddle.com/#!2/495d1/68

于 2012-05-07T11:54:40.733 に答える
0

LEFT JOIN「正しい」テーブルを含む条件を使用して、 から に移動WHEREONます。

SELECT s.display_text
     , COUNT(h.history_id) AS total_watch 
FROM 
    sys_list_of_values AS s 
  LEFT JOIN 
    history AS h
      ON  h.platform_id = s.value_id 
      AND h.video_id = 1
      AND h.created <  '2012-05-07'
GROUP BY s.value_id
  WITH ROLLUP                     --- for an additional final row with total sum

と が必要な場合は、これORDER BY display_textROLLUP使用します。

GROUP BY s.display_text
  WITH ROLLUP             
于 2012-05-07T11:47:15.487 に答える
0

サブクエリを使用して、プラットフォームのリストに対してカウントを結合できます。

SELECT display_text, IFNULL(total_watch, 0)
FROM sys_list_of_values
LEFT JOIN (
    SELECT platform_id AS value_id, COUNT(history_id) AS total_watch
    FROM history
    WHERE video_id = 1
    AND history.created < '2012-05-07'
    GROUP BY platform_id
) AS watch_counts USING (value_id)
WHERE list_group = 'platform'

ところで、特にアプリケーション コードに既存のすべてのプラットフォームの長期的なキャッシュが手元にあると仮定する場合は特に、DB で行うよりもアプリケーション コードでプラットフォームのリストを完成させる方が、通常はパフォーマンスが向上します。

于 2012-05-07T11:49:02.633 に答える
0
SELECT
  sys_list_of_values.value_id     as VID,
  sys_list_of_values.display_text,
  COUNT(history.history_id)       AS 'total_watch'
FROM sys_list_of_values
   JOIN history
    ON sys_list_of_values.value_id = history.platform_id
where sys_list_of_values.list_group = 'platform'
    and history.created < '2012-05-07'
GROUP BY history.platform_id
order by VID
于 2012-05-07T12:05:16.000 に答える