【问题标题】:How can I get the total in a many to many relationship?如何在多对多关系中获得总数?
【发布时间】:2020-07-21 05:10:41
【问题描述】:

我正在使用 wxpython 和 sqlite3 构建一个简单的歌曲管理器。

有以下表格

  • 歌曲
  • 文件
  • 标签
  • 播放列表

歌曲和文件具有一对一的关系。

歌曲和标签具有多对多关系。

歌曲和播放列表具有多对多关系。

您可以在下面看到我正在使用的表查询:

create_songs_table_query = """ CREATE TABLE IF NOT EXISTS songs (
                                song_id integer PRIMARY KEY AUTOINCREMENT,
                                title text NOT NULL,
                                artist text NOT NULL,
                                added_timestamp integer NOT NULL,
                                file_id INTEGER NULL,
                                    FOREIGN KEY (file_id)
                                    REFERENCES files (file_id)
                                    ON DELETE CASCADE
                    ); """

create_files_table_query = """ CREATE TABLE IF NOT EXISTS files (
                                        file_id integer PRIMARY KEY AUTOINCREMENT,
                                        filename text NULL,
                                        size integer NULL,
                                        song_id INTEGER NOT NULL,
                                            FOREIGN KEY (song_id)
                                            REFERENCES songs (song_id)
                                            ON DELETE CASCADE                                
                                ); """

create_tags_table_query = """CREATE TABLE IF NOT EXISTS tags (
                                 tag_id integer PRIMARY KEY AUTOINCREMENT,
                                 tag_text  text NOT NULL,
                                 tag_timestamp integer NULL,

                                ); """

create_songs_tags_table_query = """CREATE TABLE IF NOT EXISTS songs_tags (
                                    song_tag_id  integer PRIMARY KEY AUTOINCREMENT,
                                    song_id INTEGER NOT NULL,
                                            FOREIGN KEY (song_id)
                                            REFERENCES songs (song_id)
                                            ON DELETE CASCADE,  
                                    tag_id INTEGER NOT NULL,
                                            FOREIGN KEY (tag_id)
                                            REFERENCES tags (tag_id)
                                            ON DELETE CASCADE  
                                    ); """

create_playlists_table_query = """CREATE TABLE IF NOT EXISTS playlists (
                                      playlist_id  integer PRIMARY KEY AUTOINCREMENT,
                                      playlist_title text NOT NULL,
                                      created_timestamp  INTEGER NOT NULL,
                                      updated_timestamp  INTEGER NULL,
                                    ); """

create_songs_playlists__table_query = """CREATE TABLE IF NOT EXISTS songs_playlists (
                                            song_playlist_id integer PRIMARY KEY AUTOINCREMENT,
                                            song_id INTEGER NOT NULL,
                                                    FOREIGN KEY (song_id)
                                                    REFERENCES songs (song_id)
                                                    ON DELETE CASCADE,
                                            playlist_id INTEGER NOT NULL,
                                                        FOREIGN KEY (playlist_id)
                                                        REFERENCES playlists (playlist_id)
                                                        ON DELETE CASCADE  
                                        ); """

我正在尝试获取每个播放列表总共有多少首歌曲,包括任何播放列表是否有 0 首歌曲。

我使用以下查询似乎返回了所需的结果:

SELECT playlists.playlist_id, playlists.playlist_title, COUNT(songs.song_id) as total
FROM playlists 
LEFT OUTER JOIN songs_playlists 
ON playlists.playlist_id = songs_playlists.playlist_id 
LEFT OUTER JOIN songs
ON songs_playlists.song_id = songs.song_id
GROUP BY (songs.song_id)
ORDER BY total DESC

虽然,我不确定它是否完全正确,或者是否有更简单或有效的方法。

【问题讨论】:

  • 我这里使用的查询不起作用,我弄错了。
  • 您的查询应该有效。问题是您的某些 CREATE 语句在语法上不正确
  • @forpas 你能详细说明正确的语法吗?
  • 检查我的答案。

标签: python sql sqlite group-by count


【解决方案1】:

我正在尝试获取每个播放列表总共有多少首歌曲,包括任何播放列表是否有 0 首歌曲。

您确实可以从playlists 表开始,然后将songs_playlistsleft join 一起带入,然后聚合。但是,您不需要songs 表来获得您想要的结果,更重要的是,您需要group by 播放列表,而不是按歌曲:

select p.playlist_id, p.playlist_title, count(sp.playlist_id) no_songs
from playlists p
left join songs_playlists sp on sp.playlist_id = p.playlist_id
group by p.playlist_id, p.playlist_title

相关子查询也可能是一种可接受的方法,因为它避免了外部聚合的需要:

select
    p.*,
    (select count(*) from songs_playlists sp where sp.playlist_id = p.playlist_id) no_songs
from playlists p

【讨论】:

    【解决方案2】:

    SQLite 要求,如果您使用 FOREIGN KEY (columnname).... 语法定义外键,则将所有这些定义放在列的定义之后(在 CREATE 语句的末尾)。
    此外,您在必须删除的右括号之前的两个 CREATE 语句中有逗号。
    这些是不正确的陈述:

    CREATE TABLE IF NOT EXISTS tags (
       tag_id integer PRIMARY KEY AUTOINCREMENT,
       tag_text  text NOT NULL,
       tag_timestamp integer NULL, -- remove the last comma
    );
    
    CREATE TABLE IF NOT EXISTS songs_tags (
      song_tag_id  integer PRIMARY KEY AUTOINCREMENT,
      song_id INTEGER NOT NULL,
      FOREIGN KEY (song_id) REFERENCES songs (song_id) ON DELETE CASCADE, -- move to the end 
      tag_id INTEGER NOT NULL,
      FOREIGN KEY (tag_id) REFERENCES tags (tag_id) ON DELETE CASCADE  
    );
    
    CREATE TABLE IF NOT EXISTS playlists (
      playlist_id  integer PRIMARY KEY AUTOINCREMENT,
      playlist_title text NOT NULL,
      created_timestamp  INTEGER NOT NULL,
      updated_timestamp  INTEGER NULL, -- remove the last comma
    ); 
    
    CREATE TABLE IF NOT EXISTS songs_playlists (
      song_playlist_id integer PRIMARY KEY AUTOINCREMENT,
      song_id INTEGER NOT NULL,
      FOREIGN KEY (song_id) REFERENCES songs (song_id) ON DELETE CASCADE, -- move to the end 
      playlist_id INTEGER NOT NULL,
      FOREIGN KEY (playlist_id) REFERENCES playlists (playlist_id) ON DELETE CASCADE  
    );
    

    所有陈述已更正:

    CREATE TABLE IF NOT EXISTS songs (
      song_id integer PRIMARY KEY AUTOINCREMENT,
      title text NOT NULL,
      artist text NOT NULL,
      added_timestamp integer NOT NULL,
      file_id INTEGER NULL,
      FOREIGN KEY (file_id) REFERENCES files (file_id) ON DELETE CASCADE
    ); 
    
    CREATE TABLE IF NOT EXISTS files (
      file_id integer PRIMARY KEY AUTOINCREMENT,
      filename text NULL,
      size integer NULL,
      song_id INTEGER NOT NULL,
      FOREIGN KEY (song_id) REFERENCES songs (song_id)  ON DELETE CASCADE
    ); 
    
    CREATE TABLE IF NOT EXISTS tags (
      tag_id integer PRIMARY KEY AUTOINCREMENT,
      tag_text  text NOT NULL,
      tag_timestamp integer NULL
    );
    
    CREATE TABLE IF NOT EXISTS songs_tags (
      song_tag_id  integer PRIMARY KEY AUTOINCREMENT,
      song_id INTEGER NOT NULL,  
      tag_id INTEGER NOT NULL,
      FOREIGN KEY (song_id) REFERENCES songs (song_id) ON DELETE CASCADE,
      FOREIGN KEY (tag_id) REFERENCES tags (tag_id) ON DELETE CASCADE  
    ); 
    
    CREATE TABLE IF NOT EXISTS playlists (
      playlist_id  integer PRIMARY KEY AUTOINCREMENT,
      playlist_title text NOT NULL,
      created_timestamp  INTEGER NOT NULL,
      updated_timestamp  INTEGER NULL
    ); 
    
    CREATE TABLE IF NOT EXISTS songs_playlists (
      song_playlist_id integer PRIMARY KEY AUTOINCREMENT,
      song_id INTEGER NOT NULL,
      playlist_id INTEGER NOT NULL,
      FOREIGN KEY (song_id) REFERENCES songs (song_id) ON DELETE CASCADE,
      FOREIGN KEY (playlist_id)  REFERENCES playlists (playlist_id) ON DELETE CASCADE  
    );
    

    尽管您不需要最后一次加入 songs,但您的查询应该可以工作。

    【讨论】:

      猜你喜欢
      • 2023-03-31
      • 2021-04-11
      • 2018-11-09
      • 1970-01-01
      • 2020-10-13
      • 2018-08-01
      • 2020-06-25
      • 1970-01-01
      • 2016-07-20
      相关资源
      最近更新 更多