2010-11-30 124 views
2

我有一張歌曲表格,每首歌曲最多可以有3種不同的風格。所以在我的表格中,對於每首歌曲,我都有列genre1,genre2和genre3。我正在嘗試顯示列表中可用的所有流派。如何從多個mysql列中選擇不同的值並將它們放入一個PHP數組中?

這裏是一個隨便舉個例子集:

genre1 genre2 genre3 
metal  jazz 
metal  country pop 
oldies metal 
rap 
jazz  hip-hop choir 
choir  metal  jazz 

我想要的清單,在PHP完成的,按字母順序顯示可用的不同類型可供選擇。因此,它應該列出此:

  • 合唱
  • 國家
  • 街舞
  • 爵士
  • 金屬
  • 老歌
  • 流行
  • 說唱

所有幫助表示讚賞。也許我不會以最聰明的方式去做這件事,但我想不出更好的辦法。

+0

當他們從MySql進來時數據看起來像什麼?它是一個數組嗎? – Jon 2010-11-30 17:49:50

回答

3

所以單獨列不有所作爲?如果是這樣的話,你可以使用一個UNION

SELECT genre1 AS g FROM t UNION SELECT genre2 AS g FROM t UNION SELECT genre3 AS g FROM t 

如果你有一個WHERE條款,那麼你將需要複製的3倍,或使用中間臨時

祝你好運!


表:

mysql> SELECT genre1, genre2, genre3 FROM music; 
+--------+---------+--------+ 
| genre1 | genre2 | genre3 | 
+--------+---------+--------+ 
| metal | jazz |  | 
| metal | country | pop | 
| oldies | metal |  | 
| rap |   |  | 
| jazz | hip-hop | choir | 
| choir | metal | jazz | 
+--------+---------+--------+ 
6 rows in set (0.00 sec) 

分組:

mysql> SELECT genre1 AS g FROM music UNION ALL 
      SELECT genre2 AS g FROM music UNION ALL 
      SELECT genre3 AS g FROM music 
+---------+ 
| g  | 
+---------+ 
| metal | 
| metal | 
| oldies | 
| rap  | 
| jazz | 
| choir | 
| jazz | 
| country | 
| metal | 
|   | 
| hip-hop | 
| metal | 
|   | 
| pop  | 
|   | 
|   | 
| choir | 
| jazz | 
+---------+ 
18 rows in set (0.00 sec) 

計數:

mysql> SELECT g, COUNT(*) AS c FROM 
      (SELECT genre1 AS g FROM music UNION ALL 
       SELECT genre2 AS g FROM music UNION ALL 
       SELECT genre3 AS g FROM music) 
     AS tg GROUP BY g; 
+---------+---+ 
| g  | c | 
+---------+---+ 
|   | 4 | 
| choir | 2 | 
| country | 1 | 
| hip-hop | 1 | 
| jazz | 3 | 
| metal | 4 | 
| oldies | 1 | 
| pop  | 1 | 
| rap  | 1 | 
+---------+---+ 
9 rows in set (0.01 sec) 
-1

SELECT DISTINCT genre1,genre2,genre3 FROM TABEL

Description

也許你需要更好的數據庫設計... songs | genres | [song_id|genre_id]

+0

在你的例子中,我將如何獲取數組並將其放入列表中?按照你做的方式,當我獲取數組時,每行有三個字段,例如$ row ['genre1'],$ row ['genre2']和$ row ['genre3']。就像我說的,我需要一個列表中的所有東西。有沒有辦法將它們結合起來?謝謝。 – 2010-11-30 17:54:48

+1

這就是數據庫設計的問題;)只是不好的數據庫設計。創建一個名爲流派的表格,然後將流派添加到另一個表格中。你可以把它們放在一個數組中,然後對它進行排序。 – dododedodonl 2010-11-30 17:56:41

+0

啊我明白了。那麼在歌曲表中,我會通過他們在歌曲表中的ID來識別流派?所以在「流派」專欄中,我會舉例說,4 | 6 | 10?這些數字將對應於流派表中的ID。 – 2010-11-30 18:01:14

2
SELECT genre1, genre2, genre3 FROM table 

假設該共mes作爲數組陣列,然後:

function coalesce_into_array($aggregate, $row) { 
    foreach ($row as $genre) { 
     $aggregate[] = $genre; 
    } 

    return $aggregate; 
} 

$data = array_unique(array_reduce($data, 'coalesce_into_array', array())); 
sort($data); 

但是,我不會在一個嚴重的應用程序中推薦這個。數據庫設計不好。閱讀有關數據庫規範化的信息,瞭解如何改進它。

0

除非你denormalized2)流派到三列出於性能的考慮,應該有相關的歌曲和流派一個單獨的表:

CREATE TABLE SongGenres (
    song INT NOT NULL REFERENCES Songs (id) ON DELETE CASCADE, 
    genre VARCHAR(32) NOT NULL, 
    UNIQUE INDEX (song, genre), 
    INDEX genres (genre) -- improves performance for getting genre names 
) Engine=InnoDB; 

這摒棄了要求的(「十字街藍調「可以在」藍調「和」三角洲藍調「下提交,但這就是關於它)和人工限制(A3的鄉村酸屋福音浮現在腦海中)每首歌的三種流派。如果您有一套有限的流派,您可能需要製作流派專欄enumerated。該SongGenres表進行了簡化讓所有流派:

SELECT UNIQUE genre FROM SongGenres; 

另外,還可以進一步規範和創造流派單獨的表:

CREATE TABLE Genres (
    id INT PRIMARY KEY AUTO_INCREMENT, 
    name VARCHAR(32) NOT NULL, 
    UNIQUE INDEX (name) 
) Engine=InnoDB; 

CREATE TABLE SongGenres (
    song INT NOT NULL REFERENCES Songs (id) ON DELETE CASCADE, 
    genre INT NOT NULL REFERENCES Genres (id) ON DELETE RESTRICT, 
    UNIQUE INDEX (song, genre) 
) Engine=InnoDB; 

簡化了獲取所有種類名甚至更多(儘管這只是一個第二個優點):

SELECT name FROM Genres; 

到流派表的主要優點是數據正確性:如果有人拼錯流派,它不會被在流派發現噸能夠。一個潛在的缺點是它將有效的流派限制在表格中的那些流派。當然,給予SongGenres上擁有INSERT權限的用戶帳號是有意義的,所以這個限制並不嚴重。一旦你開始添加新的流派,你將面臨與沒有流派表的錯誤相同的問題:打字錯誤。而不是添加流派表中找不到的新流派,查找類似的流派(例如,使用Levenshtein distanceSOUNDS LIKE),如果找到任何流派,請詢問用戶是否要用發現的流派或保留原始類型(並將其添加到流派列表中)。

這裏的數據是什麼樣子在第一種情況下(兩個表,SongsSongGenres):

mysql> SELECT * FROM Songs; 
+----+---------------------+--------+---- 
| id | title    | artist | ... 
+----+---------------------+--------+---- 
| 1 | Cross Road Blues | ... 
| 2 | Peace In the Valley | ... 
+----+---------------------+--------+---- 
2 rows in set (0.00 sec) 

mysql> SELECT * FROM SongGenres; 
+------+-------------+ 
| song | genre  | 
+------+-------------+ 
| 2 | acid  | 
| 1 | blues  | 
| 2 | country  | 
| 1 | delta blues | 
| 2 | gospel  | 
| 2 | house  | 
| 2 | techno  | 
+------+-------------+ 
7 rows in set (0.00 sec) 

mysql> SELECT s.title, sg.genre FROM Songs AS s JOIN SongGenres AS sg ON s.id=sg.song; 
+---------------------+-------------+ 
| title    | genre  | 
+---------------------+-------------+ 
| Cross Road Blues | blues  | 
| Cross Road Blues | delta blues | 
| Peace In the Valley | acid  | 
| Peace In the Valley | country  | 
| Peace In the Valley | gospel  | 
| Peace In the Valley | house  | 
| Peace In the Valley | techno  | 
+---------------------+-------------+ 
7 rows in set (0.00 sec) 

設有一個獨立的流派表,在歌曲中的數據會看起來一樣,但在其他我們會有類似的表格:

mysql> SELECT * FROM Genres; 
+----+-------------+ 
| id | name  | 
+----+-------------+ 
| 1 | acid  | 
| 2 | blues  | 
| 3 | classical | 
| 4 | country  | 
| 5 | delta blues | 
| 6 | folk  | 
| 7 | gospel  | 
| 8 | hip-hop  | 
| 9 | house  | 
... 
| 18 | techno  | 
+----+-------------+ 
18 rows in set (0.00 sec) 

mysql> SELECT * FROM SongGenres; 
+------+-------+ 
| song | genre | 
+------+-------+ 
| 1 |  2 | 
| 1 |  5 | 
| 2 |  1 | 
| 2 |  4 | 
| 2 |  7 | 
| 2 |  9 | 
| 2 | 18 | 
+------+-------+ 
7 rows in set (0.00 sec) 

mysql> SELECT s.title, g.name AS genre 
    -> FROM Songs AS s 
    ->  JOIN SongGenres AS sg ON s.id=sg.song 
    ->  JOIN Genres AS g ON sg.genre=g.id; 
+---------------------+-------------+ 
| title    | genre  | 
+---------------------+-------------+ 
| Cross Road Blues | blues  | 
| Cross Road Blues | delta blues | 
| Peace In the Valley | acid  | 
| Peace In the Valley | country  | 
| Peace In the Valley | gospel  | 
| Peace In the Valley | house  | 
| Peace In the Valley | techno  | 
+---------------------+-------------+ 
7 rows in set (0.00 sec) 
相關問題