如何从多个mysql列中选择不同的值并将它们放在一个PHP数组中?

时间:2010-11-30 17:46:36

标签: php mysql

我有一个歌曲表,每首歌最多可以有3种不同的流派。所以在我的表中,对于每首歌我都有列genre1,genre2和genre3。我正试图在列表中显示所有类型。

这是一个随机的示例集:

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

我希望在php中完成的列表按字母顺序显示可供选择的可用不同类型。所以应该列出这个:

  • 合唱
  • 国家
  • 街舞
  • 爵士
  • 金属
  • 老歌
  • 流行音乐
  • 说唱

感谢所有帮助。也许我不是最聪明的方式,但我想不出更好的方法。

4 个答案:

答案 0 :(得分: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 :(得分:2)

SELECT genre1, genre2, genre3 FROM table

假设这是一个数组数组,那么:

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);

但是,我不会在严肃的申请中推荐这个。数据库设计很糟糕。阅读有关数据库规范化的信息,了解如何改进它。

答案 2 :(得分: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;

这消除了(“Cross Road Blues”可以在“Blues”和“Delta Blues”下提交,但就此而言)和人工限制(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;

Genres表的主要优点是数据正确性:如果有人拼错了类型,则在Genres表中找不到它。潜在的缺点是它将有效类型限制为表中的类型。当然,为SongGenres提供具有INSERT权限的用户帐户是有意义的,因此这种限制并不严重。一旦你开始添加新类型,你就会遇到与没有类型表时相同的问题:拼写错误。不是添加Genres表中没有的新类型,而是查找类似的类型(使用例如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)

使用单独的Genres表,Songs中的数据看起来会相同,但在其他表格中我们会有类似的内容:

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)

答案 3 :(得分:-1)

SELECT DISTINCT类型,流派,流派3 FROM table

Description

也许您需要更好的数据库设计...... songs | genres | [song_id|genre_id]