用于音乐图表跟踪器的 SQLite 数据库设计

SQLite database design for music chart tracker

我一直在整理一个 SQLite 数据库来跟踪 iTunes RSS 提要中排名前 100 的歌曲。我已经在 Bash 中构建了脚本来完成所有艰苦的工作,它终于开始工作了,但我不确定我的数据库结构是否正确,所以我正在寻找一些关于最佳方法的反馈因为我目前只是在学习 SQL,所以我不想在构建查询以及时检索数据时让自己陷入困境!

我有 3 个 table 是这样的;

artists_table

artist_id - PK
artist_name

songs_table

song_id - PK
artist_id - FK (from the artists table)

charts_table

chart_id - PK
song_id - FK (from the songs table)
position - (chart position 1-100)
date - (date of chart position xxxx-xx-xx)

艺术家和歌曲 table 对我来说不错,外键约束起作用...等等,但我不确定图表 table,这个结构有什么明显的错误吗?

我想跟踪 songs/artists/positions 随着时间的推移,这样我就可以生成一些统计数据...等等

谢谢,

这完全取决于您的数据将具有的关系(一对一、一对多、多对多)。

您实现图表的方式 table 表明:

  • 每个图表有 only/belongs 一首歌曲
  • 一首歌可以有很多排行榜

是一对多的关系。如果那是您的意图,那么一切似乎都很好。

但是:

  1. 如果您的排行榜可以包含多首歌曲,而一首歌曲只有一首 图表(也是一对多关系但相反),song_id 列需要 从排行榜中删除 table 并且歌曲 table 需要 chart_id 中的列。
  2. 如果您的排行榜可以有很多歌曲,而您的歌曲也可以有很多排行榜(多对多关系),那么您需要一个 "joint table",它可能是这样的: TABLE:charts_songs,列:id,chart_id,song_id,位置

初始响应

我问你数据,是为了回答你的Question,你却一直跟我讲过程。毫无疑问,这对你来说非常重要。现在您希望确保记录归档系统是正确的。

就我个人而言,在设计好数据库之前,我从来不写一行代码。部分原因是我讨厌重写代码(而且我喜欢编码)。你的顺序颠倒了,这是最近的一个不幸趋势。这意味着,无论我给你什么,你都必须重写大部分代码。

(b.1) How exactly does it check if the artist[song] already exists ?

(b.2) How do you know that there is NOT more than occ of a specific artist/song on file ?

现在,鉴于您问题中的详细信息,假设您有来信,Pussycat Dolls 今天在 MTV 排行榜上排名第 66 位:

    INSERT artist VALUES ( "Pussycat Dolls" )    -- succeeds, intended
    INSERT artist VALUES ( "Pussycat Dolls" )    -- succeeds, unintended
    INSERT artist VALUES ( "Pussycat Dolls" )    -- succeeds, unintended
  1. 今天第 66 名的 Pussycat Dolls 记录究竟是哪一项? 当你的 RFS 增长时,你在 artist 中有更多的字段,例如。 birth_date,您想更新三个记录中的哪一个?

  2. 歌曲同上

  3. 图表是如何识别的,是不是有点像US Top 40

(b.1) How exactly does it check if the artist[song] already exists ?

当您执行代码时,它会在 sqlite 程序中运行。您传递给它的确切 SQL 字符串是什么?假设您这样做:

    SELECT $artist_id = artist_id
            FROM artist
            WHERE artist_name = $artist_name
    IF $artist_id = NULL
        INSERT artist VALUES ( $artist_name )

那么当系统运行 "live" 时,您将会有一些惊喜。希望这种互动能消除它们。现在你有几百位艺术家。

  • 当你有几千个艺术家时,系统会慢得像蜗牛一样。

  • 当出现问题时,您将拥有重复的艺术家、歌曲、排行榜。

记录归档系统

现在,您有一个 1970 年代以前的 ISAM 记录归档系统,没有关系完整性、功能或速度。

如果您想了解更多关于 RFS 的危险,在当今的关系上下文中,请阅读

关系数据库

据我了解,您需要关系数据库的完整性、功能和速度。这就是您的目标。显然,它是不完整的,未经证实的,可能缺少细节,许多问题仍然悬而未决。但是我们必须对数据进行建模,仅作为数据(而不是你要用它做什么,过程),除了数据什么都没有。

这种方法将确保很多事情:

  • 随着数据的增长和添加(就结构而言,而不是人口),现有数据和代码不会改变

  • 您将拥有数据和参照完整性

  • 您可以通过单个 SELECT 命令获取您的每项统计数据。

  • 你可以对数据执行任何SELECT,甚至是你无法想象的SELECT,这意味着无限的统计数据。只要数据以Relational形式存储即可。

数据库是有关现实世界的事实的集合,仅限于关注的主题领域。到目前为止,我们没有事实,我们有一个传入 RSS 流的记录。而且录音没有完整性,你的代码没有什么可以依赖的。这是朝着事实的方向前进:

初稿音乐排行榜 TRD(由于进度已过时,见下文。)

回复评论 1

Currently, I am only tracking one chart, but I see in your model that it also has the ability to track several, that is nice!

不是真的。它是 side-effect 正确地做事。这里的问题是 Identification 之一。图表位置不是由 RSS Feed IDchart_table.id, 加一个 PositionNo 加一个 DateTime. 编号 识别的 图表位置 标识为US Top 100/27 Apr 15/1…副作用是ChartName是标识符的一部分,并且允许多个图表,无需额外编码。

在 IT 的这些黑暗日子里,人们经常为一个国家/地区编写系统,并在所有地方实施 StateCode。然后当他们向国际客户群开放时会遇到大量问题。关键是,没有一个国家没有一个国家,一个国家只存在于一个国家的背景下。所以州的标识符必须包括一个国家标识符,它是 (CountryCode, StateCode). 澳大利亚和加拿大都有 NT 用于 StateCode.

If I can explain how I store the data from the rss feed, it might clear things up somewhat.

不,请。这是关于数据的,而且只是数据。请查看我之前对该问题的评论以及好处。

I am away from my main computer at the moment, but I will respond within the next couple of hours if thats ok.

不用担心。我明天再去。

Your model does make sense to me though,

那是因为你非常了解数据的价值,但你不了解数据,当有人正确地为你列出数据时,你会体验到令人愉悦的识别的小抽搐。

I don't mind having to recode everything, its a learning curve!

那是因为您本末倒置,根据电子表格中列出的数据进行编码,而不是先设计数据库,然后再进行编码。

如果您不习惯使用符号,请注意每一个小刻度、刻痕和标记,实线与虚线,方角与圆角,都具有非常具体的含义。参考IDEF1X Notation.

回复评论 2

Just one more quick question.

开火,直到你完全满意。

In the diagram, would there be any disadvantage to putting the artist table above the song table and making the song table a child of the parent artist instead? As artists can have many songs, but each song can only have 1 artist. Is there any need for the additional table to contain just the artistPK and songPK. Could I not store the artistPK into the songs table as a FK, as a song can only exist if there is an associated artist?

  1. 注意你对组织方式的依恋。我重复:

A database is a collection of facts about the real world, limited to the subject area of concern.

事实是合乎逻辑的,而不是物理的。当这些事实被正确组织(规范化,设计)时:

You can execute any SELECT against the data, even SELECTs that you are not capable of dreaming about, meaning unlimited stats. As long as the data is stored in Relational form.

当它们不存在时,您就不能。针对数据的所有 SQL(不仅是设想的报告)都受到模型的限制,归结为一件事:离散事实是否以逻辑形式记录。

有了 TRD,我们已经开始记录关于现实世界的事实,仅受应用程序范围的限制,而不是 non-discretion 事实。

Could I not store the artistPK into the songs table as a FK, as a song can only exist if there is an associated artist?

此时此刻,在您的工作环境中,确实如此。但在您正在录制的现实世界中,情况并非如此。如果应用程序或您的范围发生变化,您将不得不更改数据库和应用程序的大块。如果您正确记录事实,因为它们存在,而不限于您当前的应用范围,则当应用或您的范围发生变化时,无需进行此类更改(当然,您必须 add 对象和代码,但不 修改现有的 对象和代码)。

在现实世界中,SongArtist是离散的事实,每个都可以独立存在。你的命题是错误的。

  • Ave MariaKaren Carpenter 记录之前存在了 16 个世纪。

  • 并且您已经理解并接受 Artist 存在而没有 `Song。

Is there any need for the additional table to contain just the artistPK and songPK.

它不是一个"additional table to contain just the artistPK and songPK",它记录的是一个离散的事实(独立于ArtistSong的独立存在),即一个特定的Artist记录了特定的 Song. That is the fact that you will count on in theChartDatePosition`

您的命题将 Song 置于 Artist 的依赖、从属地位,这是不正确的。基于 Song 的任何和所有统计数据(梦想与否)都必须导航 Artist::ArtistSong,然后排序或 ORDER BY,

artists can have many songs, but each song can only have 1 artist.

即 half-true(在您当前的工作环境中是正确的,但在现实世界中并非如此)。事实是:

  • Each Artist is independent
    Each Song is independent
    Each Artist recorded 1-to-n Songs (via ArtistSong)
    Each Song was recorded by 1-to-n Artists (via ArtistSong)

为了理解,改变你上面的话以形成正确的命题(而不是陈述技术上正确的谓词):

  • Artists can have many RecordedSongs
    Each RecordedSong can only have 1 Artist Each RecordedSong can only have 1 Song

所以是的,有缺点,很明显。

这就是我声明的原因,你必须将自己与应用、使用和建模数据分开,作为数据,只有数据

解决方案 2

我已经更新了 TRD。

二稿Music Chart TRD

  • Courier表示示例数据;蓝色表示一个 Key(Primary 总是第一个);竖线表示柱分离;斜线表示Alternate Key(只显示不在PK中的列);绿色表示 non-key。

  • 我现在给你谓词。这些非常重要,原因有很多。 这里的主要原因是它消除了我们正在讨论的问题的歧义。

    • 如果您想了解有关 Predicates 的更多信息,请访问 ,向下滚动(向下滚动!)至 Predicate,然后阅读该部分。还要评估 that TRD 和 those Predicates against it.
  • ChartDateSong 上的索引需要解释。起初我假设:

       PK ( Chart, Date, Rank )
    

    但是出于完整性和搜索目的,我们需要:

       AK ( Chart, Date, ArtistId, SongId )
    

    哪个更好PK。所以我换了他们。我们确实需要两者。 (我不知道 NONsqLite,如果它有聚集索引,AK, 而不是 PK 应该被聚集。)

       PK ( Chart, Date, ArtistId, SongId ) 
       AK ( Chart, Date, Rank )
    

回复评论 3

What about the scenario when a song enters the charts with the same song_name as a record in the song_table but is completely unrelated (not a cover, completely original, but just happens to share the same name)

在文明国家这叫作弊,以欺骗手段获取利益,但我还是试着用魔性的思维来回答一下问题。

好吧,如果它发生了,那么你就得迎合它。提要如何通知您此类事件?我相信它不会。那么您的歌曲标识符仍然是名称。

and instead of a unique song record being created, the existing song_id is added to the artistssongs_table with the artist id, wouldn't this be a problem?

我们不知道更好,所以这不是问题。没有人看那个提要也知道得更多。如果以及当您通过任何渠道收到通知您该问题的数据并且您可以指定它时,您可以更改它。

通常我们有一个应用程序允许我们浏览层次结构并更改它们,例如。一个 ReferenceMaintenance 应用程序,左侧是 Exporer-type window,右侧是组合对话框(顶部是 occ 列表,底部是一个 occ 的详细信息)。

在那之前,它不是一种腐败形式,因为防止这种腐败的约束是未定义的。你不能因为违反了尚未成文的法律而被定罪。除了流氓国家。

Although a song can have the same name, it doesn't necessarily mean it's the same record.

是的。

Wouldn't it be better to differentiate a song by the artist?

它们由艺术家区分的。

您明白歌曲的事实和艺术家演奏歌曲的事实是两个独立的事实,是吗?请质疑任何不完全意义上的谓词,这些是数据库支持的命题。

  • Ave Maria作为一个独立的事实存在,在Song

  • Karen Carpenter, Celine Dion, and Yours Truly作为三个独立的事实存在,在Artist

  • Karen Carpenter-Ave Maria, Celine Dion-Ave Maria, and Yours Truly-Ave MariaArtistSong.

  • 中作为三个离散的事实存在
  • 那是七个独立的事实,大约一个Song,大约三个Artists.

回复评论 4

I do understand it now. The artistsong_table is where the 2 items "meet" and a relationship actually exists and is unique.

是的。我只是不会那样说。 Fact 一词在技术上具有精确的含义,高于英语含义。

A database is a collection of facts about the real world, limited to the subject area of concern.

考虑到对 Fact 的理解,或许再读一遍我的回复 3。

  • 每个 ArtistSong 行都是一个事实。这取决于艺术家的事实和歌曲的事实。它确定了那个艺术家录制了那首歌的事实。并且 ArtistSong Fact 是层次结构中较低级别的其他 Fact 所依赖的。

  • "Relationship ... actually"。我想你的意思是 "instance"。 table之间是有关系的,因为我画了一条线,你要实现一个Foreign Key Constraint。也许将 Fact 视为 "instance".

Just to make sure I understand the idea correctly, if I were to add "Genre" into the mix, would I be correct in thinking that a new 'independent' table genre_table would be created and the artistsong_table would inherit its PK as an FK?

是的。它是经典的参考或查找 table,关系将是 Non-identifying。我对音乐妓院的了解还不够多,无法发表任何声明,但据我了解,流派适用于歌曲;一个艺术家;和 ArtistSong(他们可以播放与 Song.Genre 不同流派的歌曲)。你给了我一个,我来做模型。

这样做的结果是,当您在 ArtistSong 中插入行时,您将必须具有流派。如果它在 Feed 中,那很好,如果没有,则您需要处理处理问题。克服的简单方法就是实现一个流派“”,它告诉你你需要从其他渠道确定它。

稍后添加分类器(例如流派)很容易,因为它是 Non-identifying 关系。但是标识项很难在以后添加,因为它们会迫使 Key 发生变化。请参阅我的回复 1 下的第 3 段。

您可能已准备好使用数据模型:

第三稿Music Chart Data Model