2017-04-01 9 views
1

私は、ユーザーが見たいビデオのスケジュールを作成できるようにするシステムを持っています。次のMySQLはアクティブスケジュールを取得し、スケジュール内のビデオ数、既に視聴している数、および今日見られる予定の数に関する情報も取得します。これは、スケジュールとビデオの関連付けを追跡する同じテーブルへの複数の結合を介して行われます。なぜこのMySQLにはCOUNT(DISTINCT ...)が必要ですか?

SELECT 
    schedules.*, 
    COUNT(DISTINCT sv1.vid_id) AS total_vids, #<-- the problem 
    GROUP_CONCAT(DISTINCT sv1.context_node_id) AS topics, 
    COUNT(sv2.vid_id) AS vids_watched, 
    COUNT(sv3.vid_id) AS today 
FROM schedules 
JOIN schedule_vids sv1 ON schedules.id = sv1.schedule_id 
LEFT JOIN schedule_vids sv2 ON schedules.id = sv2.schedule_id && sv2.watched IS NOT NULL 
LEFT JOIN schedule_vids sv3 ON schedules.id = sv3.schedule_id && sv3.date = CURDATE() 
WHERE user_id = ? && schedules.id = ? 
GROUP BY schedules.id 
ORDER BY created DESC 

問題:私はCOUNT (DISTINCT sv1.vid_id)(すなわち、ちょうどCOUNT(sv1.vid_id))を使用していない場合、私はこれまで、真数を超える数を取得します。私はDBでこれを確認しました。私はどこに間違っているのか誰にでも見える?

興味深いことに、sv3(とselect文の対応する部分)への結合を削除すると、問題はなくなります。

[UPDATE]

ここ関与する2つのテーブルのテーブル構造は次のとおり

CREATE TABLE `schedules` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`name` varchar(50) NOT NULL, 
`user_id` varchar(11) NOT NULL, 
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
`start` date NOT NULL, 
`end` date NOT NULL, 
`inc_weekends` enum('y') DEFAULT NULL, 
`type` enum('ls','c') NOT NULL DEFAULT 'ls' COMMENT 'ls = learning schedule; c = course', 
`subj_id` varchar(30) NOT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=MyISAM AUTO_INCREMENT=51 DEFAULT CHARSET=latin1 

CREATE TABLE `schedule_vids` (
`schedule_id` int(11) NOT NULL, 
`vid_id` varchar(11) NOT NULL, 
`context_node_id` varchar(11) NOT NULL, 
`date` date NOT NULL, 
`watched` date DEFAULT NULL, 
PRIMARY KEY (`schedule_id`,`vid_id`,`context_node_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

サンプル出力:

id    50 
name   some-schedule 
user_id   yd8i0i63bd8 
created   2017-04-01 11:58:22 
start   2017-04-01 
end    2017-04-03 
inc_weekends y 
type   ls 
total_vids  91 
topics   maths 
vids_watched 0 
today   91 
+1

サンプルデータと望ましい結果は、他の人がこの問題を理解するのに役立ちます。 –

+0

更新中....... – Utkanos

答えて

2

すべての可能性において、あなたにはdistinctが必要です。問題はあなたの結合です。代わりに条件付き集計を使用してください。

SELECT s.*, 
     COUNT(*) AS total_vids, #<-- the problem 
     GROUP_CONCAT(DISTINCT sv.context_node_id) AS topics, -- distinct is probably still needed here 
     COUNT(watched) AS vids_watched, 
     SUM(sv.date = CURDATE()) AS today 
FROM schedules s JOIN 
    schedule_vids sv 
    ON s.id = sv.schedule_id LEFT JOIN 
    school_users su 
    ON s.user_id = su.uid -- I'm guessing `user_id` comes from s 
WHERE s.user_id = ? AND s.id = ? 
GROUP BY s.id 
ORDER BY s.created DESC; 

集計なしでクエリを実行すると、何が起きているかがわかります。ビデオのデカルト積を得ているので、カウントがオフになっています。

+0

ご協力ありがとうございます。しかし、私は "フィールドリスト"で "未知の列 'sv3.date'"を取得しています - あなたが 'sv3'をどこで定義したのかわかりません。 – Utkanos

+0

そして、 'COUNT()'ではなく 'SUM()'の理由は何ですか? – Utkanos

+1

私はsv3がちょうどsvでなければならないと思う、それは偶然に残された。 –

関連する問題