计算多个连接的更好方法

时间:2013-12-29 00:26:59

标签: mysql sql

教会管理网站的崇拜歌曲模块的模式如下:

歌曲 - id,name

song_books - id,name,available

books_songs - 歌曲和歌曲书籍之间的多对多关系,每首歌可以有多本书中的数字,如果教会使用多本书,任何数字都可以。

song_tracks - id,date,leader,service - 对日期和服务的唯一约束。

songs_led - id,track_id,song_id - 特定跟踪日的歌曲列表。

下面的查询会获得一个时间范围内的歌曲列表,一个书名和数字,以及它被引导的次数。

...as "count"声明

COUNT(`l`.`song_id`)

之前,但是当一首歌出现在多本书中时它的数量增加了一倍,所以我除了一首歌出现的可用书籍数量。

SELECT `s`.`name`,
       `s`.`id`,
       `bs`.`number`,
       `b`.`name` AS `bname`,
       CEIL(COUNT(`l`.`song_id`)/
              (SELECT COUNT(songs.id)
               FROM songs
               LEFT JOIN books_songs ON books_songs.song_id = songs.id
               AND books_songs.book_id IN
                 (SELECT id
                  FROM song_books
                  WHERE available <> 0)
               WHERE songs.id = s.id)) AS `count`
FROM `songs` AS `s`
JOIN `songs_led` AS `l` ON (`l`.`song_id` = `s`.`id`)
JOIN `books_songs` AS `bs` ON (`bs`.`song_id` = `s`.`id`)
JOIN
  (SELECT *
   FROM song_books
   WHERE available <> 0
   ORDER BY name ASC) AS `b` ON (`bs`.`book_id` = `b`.`id`)
JOIN `song_tracks` AS `t` ON (`l`.`track_id` = `t`.`id`)
WHERE `t`.`date` >= '2013-10-29'
  AND `t`.`date` <= '2013-12-28'
GROUP BY `s`.`id`
ORDER BY `count` DESC,
         `s`.`name`,
         `b`.`name`

有更好的方法吗?我希望将来不要陷入这种加入地狱。

1 个答案:

答案 0 :(得分:1)

如果每首歌曲都有自己的ID,即使它出现在多本书中,那么您也可以使用

   COUNT(DISTINCT song_id)

避免重复计算出现在多本书中的那些。