Need help with Arrays

Well:

  • Each artist has multiple albums
  • Each album has multiple songs

Hence it makes no sense than to do anything other than:


$Music = array(
    'Coldplay' => array(
        'A Rush of Blood to the Head' => array(
            'Politik',
            'In My Place',
            'God Put A Smile Upon Your Face',
            'The Scientist',
            'Clocks',
            // ...
        ),
        'Mylo Xyloto' => array(
            'Mylo Xyloto',
            'Hurts Like Heaven',
            'Paradise',
            'Charlie Brown',
            // ...
        )
        // ...
    ),
    'Phil Collins' => array(
        'Face Value' => array(
            'Behind The Lines',
            'Droned',
            'Hand In Hand',
            // ...
        )
    )
);

So it goes $Music[-artist-][-album-][-song-], i.e. $Music[‘Coldplay’][‘Mylo Xyloto’] contains an array of the songs.

But how do you do this with a database? Well it’s a different set up to the arrays:

CREATE TABLE Artists(
     ID int(11) AUTO_INCREMENT,
     Name varchar(56),
     PRIMARY KEY (ID)
);
CREATE TABLE Albums(
     ID int(11) AUTO_INCREMENT,
     Name varchar(56),
     PRIMARY KEY (ID)
);
CREATE TABLE Songs(
     ID int(11) AUTO_INCREMENT,
     Artist int(11),
     Album int(11),
     Name varchar(56),
     PRIMARY KEY (ID)
);

INSERT INTO Artists (Name) VALUES
     ('Coldplay'),
     ('Phil Collins');

INSERT INTO Albums (Name) VALUES
     ('A Rush Of Blood To The Head'),
     ('Mylo Xyloto'),
     ('Face Value');

INSERT INTO Songs (Artist, Album, Name) VALUES
     (1, 1, 'Politik'),
     (1, 1, 'In My Place'),
     (1, 1, 'God Put A Smile Upon Your Face'),
     (1, 1, 'The Scientist'),
     (1, 1, 'Clocks'),
     (1, 2, 'Mylo Xyloto'),
     (1, 2, 'Hurts Like Heaven'),
     (1, 2, 'Paradise'),
     (1, 2, 'Charlie Brown'),
     (2, 3, 'Behind The Lines'),
     (2, 3, 'Droned'),
     (2, 3, 'Hand In Hand');

The reason I chose not to give albums an artist (and give songs just an album) is that sometimes albums contain multiple artists (compilation albums, for example).

To construct the above array:


$Music = array();
$MusicQuery = mysql_query('SELECT a.Name Artist, al.Name Album, s.Name Song FROM Songs s INNER JOIN Artists a ON s.Artist = a.ID INNER JOIN Albums al ON s.Album = al.ID');
while(list($Artist, $Album, $Song) = mysql_fetch_array($MusicQuery)){
    if(!isset($Music[$Artist])){
        $Music[$Artist] = array();
    }
    if(!isset($Music[$Artist][$Album])){
        $Music[$Artist][$Album] = array();
    }
    $Music[$Artist][$Album][] = $Song;
}
var_dump($Music);

That’s a bad idea. My database model still is better:

I would arguably change song:

  • one for group: ( group id, group name ),
  • one for album: ( foreign group id key, album id, album name )
  • one for song: ( foreign album id key, song id, song name )

<hr>

In those special cases of compilation albums, you create a new group/band (e.g. “V.A. 58”) and have the group/band description and componence in another table, like you should have for the other groups/bands too.

<hr>

If I simplify my array and strictly keep only the bands name, their albums titles and their corresponding songs titles, then it’s the same thing:


$band_name = 'Led Zeppelin';
$album_title = 'Led Zeppelin III',

$the_songs = $bands[$band_name][$album_title];  

itmitică,

Thanks for the awesome examples!!! (I think you’ve helped me best to understand things from different angles.)

Debbie

Thanks.

I guess this is what you were looking for: a little recognition for your idea and a little help to make it work. :slight_smile:

Well, not as much “recognition” and just a sense check that how I was envisioning things was one valid way to do things.

It’s not a new idea, but it’s good you’ve thought about it, because databases and arrays don’t necessarily translate one to another. Classic relational databases have stricter rules, but with arrays we can be more flexible.

Yes, I can see that. And as you can probably see, I like the more formal nature of Relational Databases, personally!

PS BTW, band entries in $bands are on their way to look like objects. :wink:

Yes, I also noticed that. (And since I hope to start learning OOP after I finish Release #2, we might be talking about Led Zeppelin some more in the near future…) :lol:

Not necessarily true, but, just for fun:

  • a band = 1 object (definitely)
  • a band album = 1 object as a property for the band object (maybe)
  • a song = 1 object as a property for the album object property of the band object (unlikely)

What you’re missing are some methods to help define the behavior of the band.

Yep.

Thanks for all of the help (in addition to those above).

Debbie

It makes no sense to change the station either… :wink:

Debbie

You’re most welcome. Looking forward to our next Led Zeppelin talk. :slight_smile:

This guy could sing the phonebook and I’d still listen to it.

In those special cases of compilation albums, you create a new group/band (e.g. “V.A. 58”) and have the group/band description and componence in another table, like you should have for the other groups/bands too.

That, my friend, is called a bodge.

Compilation albums aren’t really a special case - look at the huge popularity of compilation albums such as “Now that’s what I call music” etc. What you’re suggesting is (for example) going onto an artist’s page and not seeing their contributions to compilation albums because they aren’t linked to that album.

The artist/album relationship is not a one-to-many relationship. It’s commonly seen that way, but it just isn’t the case. If you are skeptical of what I’m saying, look at the most popular softwares out there - like iTunes, WMP, Winamp etc. If you search for an artist, you don’t expect just to get the songs from their own albums, especially if you don’t own all of their albums. You get any song they have written, regardless of if the album was their own.

Certainly not. I guess you didn’t quite read this?

[QUOTE=itmitică;5129551]
In those special cases of compilation albums, you create a new group/band (e.g. “V.A. 58”) and have the group/band description and componence in another table, like you should have for the other groups/bands too.[/QUOTE]

When you look up an artist, on that table you will get not only all relations to all its albums === all its songs, but also to all the bands it was ever part off. Because, isn’t it, the artist/band is not a one-to-one relationship, is it? :wink:

Right, the search results in a front-end interface are suppose to tell me something relevant about the ER model behind? I think I’ll trust my DB knowledge instead. :slight_smile:

Of course the artist/album is a one-to-many relationship! Even if the artist releases a single, it would be an album with the name of that single. And it has nothing to do with “owning”! If the rights are sold to a record house, the artist name doesn’t still appear on the album cover? If you mean that it’s not an exclusive relation, that would be true. But it’s another thing altogether.

And please don’t read special as rare. When I said “V.A. 52” it means “Various Artists 52”. I believe they greatly precede “Now that’s what I call music” compilations… …and 52 isn’t to express rare.

If a song is given only an album, and the album is given a list of artists, there is no direct isolating link between an artist and their song; A search for the artist would bring up the entire album (rather than their own songs on it), as you’re suggest the album is linked to all of the artists.

I’m not criticising your approach, but it is certainly less efficient. With the layout I proposed above, I used 3 tables. At most, it requires N+1 records for an album of N songs, each with a different artist, assuming the artist was existing in the database, and the +1 being for the album’s record. Each song knows which artist it belongs to. I’d like to see your approach to the same problem - again, I’m not criticising it, but calling my approach ‘bad’ is rather rude and, until I’m shown a more efficient approach, completely invalid as far as I’m concerned.

A possible down side that both of ours’ share is that, if a song is on two albums, it requires two records. However it can be justified - quite often the songs aren’t copies but are, instead, new recordings.

Certainly not true. I see here some understanding issues regarding relational databases on your part.

Here is your BIG logic fault: a song title is different from a song id. You’re mixing up keys and values. They exist for a reason, both in databases and in arrays. A song may gave the same value in the title column. If in its complete description there is at least one column that makes it different from another already existing record in the table, a new id will be created, and you’ll have two different records. Somewhat similar, yes, but different, nonetheless. That’s DB.

Yeah, and I was believing that “certainly less efficient” is a good thing. LOL

No, my approach is called normalization. For those that understand it. Your approach is the one extremely inefficient and confused!

I understand your first point. Truthfully, though, the array wouldn’t be an array. It’d be a MusicCollection object. Artists, Songs and Albums would be objects accessing whatever they will. If you honestly believe my code suggested the title being a key or ID, you need to look at the code again.

As for normalisation, you seem to be mislead. Normalisation is strictly against making things more complicated than they need to be. Normalisation is splitting of parts into separate identities and not reusing information - whilst keeping dependencies low. Creating a new table for band information ON TOP of a pre-existing band information table is called over-normalisation. Giving a compilation album a pseudo-artist makes little sense.

Again, show me a better approach (structure and code) and I will accept that yours is a better approach, for the following things (I’ve supplied queries with my own approach for comparison):

  • Grab all song names by their artist ID, ordered by name ascending:

    sql SELECT DISTINCT(Name) FROM Songs WHERE Artist = :ArtistID ORDER BY Name ASC
  • Grab all artists’ names in an album by album ID

    sql SELECT DISTINCT(a.Name) FROM Artists a INNER JOIN Songs s ON s.Artist = a.ID WHERE s.Album = :AlbumID
  • Select all artists with their albums and songs:

    sql SELECT a.Name Artist, al.Name Album, s.Name Song FROM Songs s INNER JOIN Artists a ON s.Artist = a.ID INNER JOIN Albums al ON s.Album = al.ID

For those that understand it.

I can assure you, arrogance is not a substitute for constructive debate. Whilst Debbie’s question has been answered from numerous angles, I believe it’s important to distinguish the more effective approach.

I promise to “certainly be less arrogant” if you promise that too, “my friend”, OK? :wink:

Just to be clear, my first point was about tables too. Your “If a song is given only an album” suggested to me you’re doing that: taking the song title as a database table unique record key. Otherwise, I don’t recall myself suggesting anything like that. Certainly two songs can have the same title, even if one it’s not a cover for the other.

<hr>

Right off the top of my head, to my already existing:

  • one for group: ( group id key, group name ),
  • one for album: ( foreign group id key, album id key, album title )
  • one for song: ( foreign album id key, song id key, song title )

I raise you this:

  • one for artist: ( foreign group id key, artist id key, artist name )

THAT’S IT! REALLY!!!

Off Topic:

Yours, database model and array, are a bad copy of mine, and that’s why I first responded. Bad in my opinion. I guess we can both agree to disagree. I’m OK with it.

I mentioned this before, but I’ll give you a real-life example of how that would break down:

The “Now That’s what I call music 81” album. Huge seller, top seller for Albums on iTunes when it was released.

This is the lineup:

Somebody That I Used To Know - Gotye feat Kimbra
Paradise - Coldplay
Lego House - Ed Sheeran
Next To Me - Emeli Sandé
Stronger (What Doesn&#8217;t Kill You) - Kelly Clarkson
Domino - Jessie J
Titanium - David Guetta feat Sia
Good Feeling - Flo Rida
The One That Got Away - Katy Perry
Last Time - Labrinth
Mama Do The Hump - Rizzle Kicks
Dance With Me Tonight - Olly Murs
Kiss The Stars - Pixie Lott
One Thing - One Direction
Seven Nation Army - Marcus Collins
Shake It Out - Florence + The Machine
Take Care - Drake feat Rihanna
Born To Die - Lana Del Rey
Cannonball - Little Mix
Proud - JLS
Wherever You Are - Military Wives Choir
Sexy And I Know It - LMFAO
Wild Ones - Flo Rida feat. Sia
Marry The Night - Lady Gaga
Levels - Avicii
International Love - Pitbull feat Chris Brown
Dedication To My Ex (Miss That) - Lloyd feat Andre 3000 & Lil Wayne
She Doesn&#8217;t Mind - Sean Paul
Troublemaker - Taio Cruz
Elephant - Alexandra Burke feat. Erick Morillo
Antidote - Swedish House Mafia vs Knife Party
When I Was A Youngster - Rizzle Kicks
Love Me - Stooshe feat. Travie McCoy
Get Yourself Back Home - Gym Class Heroes feat. Neon Hitch
You Da One - Rihanna
Bright Lights (Good Life) - Tinchy Stryder feat. Pixie Lott
Twilight - Cover Drive
Alone Again - Alyssa Reid feat. Jump Smokers
Who You Are - Jessie J
Ray Charles - Chiddy Bang
T.H.E. (The Hardest Ever) - Will.i.am feat. Mick Jagger / Jennifer Lopez
RockStar - Dappy feat Brian May

So, what happens if I wanted to search for all songs by ‘Gotye’, but the song I’m looking for is purely on this Now That’s What I Call Music 81 album:

SELECT s.Name FROM Songs s INNER JOIN Artists a ON s.Artist = a.ID WHERE Artist LIKE '%Gotye%'

.
That would find the first song of the album.

However, what happens if I search for Gotye using your proposal?

SELECT s.Name FROM Songs s INNER JOIN Albums al ON song.album = album.id INNER JOIN GroupMembers m ON album.`Group` = m.`Group` WHERE m.Name LIKE '%Gotye%'

It would return ALL of the results for the album, even though I only want to find Gotye.

So, I uphold that a distinct relationship needs to be made between songs and artists, as well as albums and songs, but artists and albums have a weak relationship.

I also mentioned this before:

It’s wrong what you’re doing, making assumptions about the ER model, based on search results, i.e. compilation album listings.

<hr>

The ER model it’s a bit more complicated than what I have showed for, but it’s certainly true what I’ve said in the previous post.

Again, right at the top of my head:

  • one for group: ( group id key, group name ),
  • one for album: ( foreign group id key, album id key, album title )
  • one for song: ( foreign album id key, song id key, song title )
  • one for artist: ( foreign group id key, artist id key, artist name )

with this addition:

  • one for compilation: ( foreign song id key, compilation id key )

or something like that. If you really really want, I can provide you with a full ER model, but I believe it’s enough to make my point.

That’s how you find your Gotye.

<hr>

These compilations are just that: compilations of information from preexisting albums. These won’t be recorded as rightful albums in the database. They will always point to the original songs (and albums (and artists)). The compilation album listing doesn’t show that, true, but that’s how you keep redundant information out of your database.

<hr>

The absurd case the Gotye song would only appear on that Now That’s What I Call Music 81 album… is absurd. The information on songs on that listing is different from that on songs from a normal album.

Following a model for all songs in your database based on that, would mean making a rule out of an exception. This would make normal albums exceptions and compilations the norm in your ER model.

Given the fact that most of the information in your database is made out of normal albums, it would make for a poor decision and for a poor ER model.

<hr>

From what I gather so far, you’re basing your decision on front-end search results and on SQL statements. It doesn’t work like that. You first build a database, then you query data and make reports. You adapt your SQL statements to your well thought database, not the other way around.

You need to think more about the architecture of your database first, about the ER model. After that comes the SQL and reporting, i.e. compilation album listing.

Incorrect. Ok, for the case of Gotye - but there are millions of compilation albums out there which have songs which don’t belong to an album. As a major example - remix albums. Dance albums commonly have songs on them which purely belong to that compilation album and nothing else. Another example - covers albums, which are getting increasingly popular: albums with many artists covering eachothers’ songs. There are also soundtrack albums with artists which have no CDs out.

Not only that, but as I said before - the album which the song may have come from may not be present on my database. Sure, when adding a compilation, the user could go through the process of finding where that song could have come from. But that’s a little redundant.

Everything you have mentioned, my method can do easily with just 3 tables. Your amount of tables is increasing per request. A compilation IS an album. It’s not a special collection of songs from other albums - its an album in its own right. Otherwise Now Thats What I Call Music (chosen for that reason) wouldn’t have been top of the iTunes Albums list, would it? On a website with album listings, you’d now have to emulate albums from compilations, by treating them as if they were albums.

From what I gather so far, you’re basing your decision on front-end search results and on SQL statements. It doesn’t work like that.

I can certainly beg to differ. The most important part of an application is how it and the users interact. Heck, not just the users - how it interacts with itself. Whenever I build a framework, it’s based on “How would I like to be able to use this”. In fact, the first thing I do when I’m building a new framework is write a module (e.g Products) and think ‘Ok, ideally how would I like to write this?’. Utilise a framework that doesn’t even exist yet in the most basic form possible… like do something like:

class ProductsHomeContent extends Content{
    protected $Products = array();
    public function processContent(){
        $ProductMapper = new ProductMapper($this->Database);
        $this->Products = $ProductMapper->getPromotions();
    }
    public function output(){
        Content::outputTemplate('Products', 'Home', array('Products' => $this->Products));
    }
}

And from that build a content class to extend from which is given a database by the controller - with a static function to output a template based on given variables, build a product mapper like:

<?php
class ProductMapper extends Mapper{
    function initialise(){
        parent::initialise('Products', 'ProductRecord');
    }
    function getPromotions(){
        return $this->getJoin('Promotions', array('ID' => 'Product'), array('Promotion' => true), '15', 'EndDate ASC');
    }
}

And from THAT build a main mapper class which has an initialise method to set the table name and record type, a get method, a getJoin method, etc etc etc.

It’s the same approach as writing interfaces and using them, before even writing anything that implements said interface. Working backwards like that is quite efficient, and it means that every step has already been planned by deciding how you want to use it, rather than choosing how to use it based on how it was written.

Thinking like that prevents you from having to compromise by having to make a separate compilation listing instead of displaying them with albums where they belong. And if you want to distinguish them, just look for albums which have songs by different artists or not.

I’d like to point out at this stage that I’ve cheated a little - I had a radio station as a client a couple of months ago.

You are incorrect. You’re still thinking reports, not database. If a song in a compilation is not found in the existing albums, it would be recorded as a single album.

The above. And a VERY WEAK ARGUMENT! The lack of data shouldn’t have to influence the database architecture.

Is this a measure of success for you? Because I can put my ass to work and probably do it easier with just one table!

Since when a ER model has to do with a certain number of tables??? If you believe less tables equals less tablespace and more speed, then you’re wrong.

WHAT??? You probably mistake records with tables! LOL

Well, as a DB Architect and DB Administrator, I certainly can’t argue with that! LOL LOL

What’s with these “arguments”. Are you really believing them? A compilation is not a collection??? Can you be more specific. :slight_smile:

Anyway, reports (album listings) are not the DIRECT reflection of the ER model (stored albums). The Golden Rule. Remember that.

What this has to do with the database? With its ER model? At all???

Is this suppose to impress me? I’m working with databases since 1998, and on big Oracle ones, with millions of records. I’ve also produced applications for Oracle databases, starting with Visual FoxPro, going through Developer, APEX or simply html/css/php ones.

I’d like to point out that you’ve cheated on the radio station too: you probably didn’t give them the best architecture for their database. You should’ve turn to a better DB professional for that part.

I’m saying this because you’re still thinking wrong: you’re creating the interface, you’re considering the reports and you fail to build the database based on properly normalized data because you can’t look past interface and reports. It’s not how it works, and it’s not proper thinking for databases, especially for serious ones.

<hr>

Compilation albums are compilation. Compilation album listings, like album listings, are reports. Reports don’t directly reflect the ER model, that’s for databases made by kids. Compilations are tables made of keys, not of data. They point to the original songs, they don’t redundantly store songs data. If you did it otherwise because you lack the proper info, then you’re the one botching it up big time.

<hr>

What I understood so far, is that, for you, the application dictates the normalization, not the relations in the data you have. Well, it’s wrong. You must have the two working together AFTER you properly design them independently.

The front-end doesn’t dictate the database architecture, the database architecture doesn’t dictate the user interface. And potentially missing data doesn’t influence the ER model.

<hr>

This is a forum. It uses BBCode, not HTML; There is not one way of doing everything everywhere. Your lovely speech about Reports etc was highly moving, however you need to understand the music industry before you can put a database to it. In the music industry, an album is just a collection of songs. The songs are by an artist. They are the only strong links. That is not a made up argument, that is a fact.

And I do hope you didn’t realise that you just tried to argue that top-down development is ‘for kids’; Because if you had realised you said that, I should have realised earlier that I was feeding a troll.

Compilations are tables made of keys, not of data. They point to the original songs

You’re thinking of playlists. Not compilation albums. Compilation albums are albums. If an original album didn’t exist (which does happen, I’ve dealt with it before), or if the album information isn’t available (again, happens) then you’re pointing to a song which has no album information, and therefore no artist.

Try something out, will you? Go onto itunes, and find a song which belongs to a compilation - or if you don’t have that, create an album of compilations and import it. Then, rename a song on it. Notice how the song on another album is unmodified; By your reckoning, you know the industry better than the guys at Apple…

If you’d like to PM this pointless debate, go ahead. I don’t want this thread hijacked more than it already is.

In fact - here’s a direct example. In Coldplay’s ‘Mylo Xyloto’ album, “Paradise” is LONGER than in the “Now that’s what I call music 81” compilation album - they’re different versions. But the only one on any of the albums (solely by Coldplay) is on the ‘Mylo Xyloto’ album. For that case, where would you suggest linking that compilation album’s “Paradise” to? A non-existent album by Coldplay?

That’s redundant data.

Your point certainly makes sense if:

  • You have a (massive) list of all albums made by everyone
  • The compilation album had the same versions of songs that were on a given artist’s album (which you’d then have to find when importing)
  • All of the songs on compilations came from an album in the first place.

But the first isn’t exactly plausible. Music is coming out all the time all over the world and I don’t believe a single source provides information for every single one of them. The latter two are just false.

No, not playlists. Pretty sure. You don’t see me telling you to go to online stores or using media players to figure out the ER model behind, do you? So, again, no, I don’t confuse one with the other. I know how a real database looks like.

<hr>

One big question: if a song doesn’t have an artist (think of anonymous folk songs), how do you record it in your database? I’m sure you, at least, put “N/A” in there, right? Which is still data. It’s not .NULL., if you know what I mean.

Which brings us back to the “problem”. If the original album doesn’t exist in your database, you create it, like any other previously nonexistant albums in your database. You don’t have the exact precise info on it, that’s not an excuse to go ahead and think sideways. You make it a single album, you put default data to be changed with real data later on and so on. But you stick to a solid ER model. Circumstances are not dictating anything regarding the database architecture.

So compilation albums only point to already existing songs in already existing albums. That’s how you track down the corresponding artists.

Off Topic:

<hr> - those that understand, understand. Those that don’t point it out or send me childish PMs with links to BBcode explanations. I can actually produce proof on that, I’m not just saying it.

You don’t build top-down, you build in parallel and you then put it together by abstraction.

I don’t have a wish to continue this over PM or otherwise, for me it’s over here and now.

If a song doesn’t have an artist, it’d have -1 as the artist, correct. But I don’t really see the point in treating a compilation album as a pseudo-album with links to existing albums, if the case may be that those albums don’t exist - sure you can create a pseudo-album for that (you couldn’t point to nothing, as no artist would be found), but all of that just creates more steps between a valid solid relationship - a song and it’s author. However, that seems to be two contrasting points of view which won’t be changing any time soon, so we should just leave it at that :lol: Don’t presume because it says ‘University’ below my badge that I’m inexperienced - I was once a Programming Team staff member around these parts before physics took over :wink:

[ot]

Those that don’t point it out or send me childish PMs with links to BBcode explanations.

That is quite childish, but you can always report them. I just pointed it out in that post to use as an example of “this has a place where it should be used, but in some situations there are valid working alternatives”. Although there is a nerd twitch in my eye whenever I see <hr> anyway - you see, it’s designed to make a break between parts of content, but truthfully if there are distinct areas of content, they should each be enclosed as their own identity, e.g. a <section> in HTML5. In BBCode that obviously doesn’t work, but as your posts flow just fine there isn’t a direct need for the separation.[/ot]