繁体   English   中英

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

[英]How do I select distinct values from multiple mysql columns and put them in one PHP array?

我有一张歌曲表,其中每首歌曲最多可以有3种不同的流派。 因此,在我的表格中,对于每首歌曲,我都有一列genre1,genre2和genre3。 我正在尝试在列表中显示所有可用的流派。

这是一个随机的示例集:

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

我希望该列表以php完成,以字母顺序显示可供选择的不同流派。 因此,它应该列出以下内容:

  • 唱诗班
  • 国家
  • 嘻哈(音乐
  • 爵士乐
  • 金属
  • 老歌
  • 流行的
  • 敲击

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

因此,单独的列没有区别吗? 如果是这样,您可以使用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)
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 )类型到三列出于性能的考虑,应该有相关的歌曲和流派单独的表:

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的乡村酸性房屋福音)三个歌曲每首流派的要求。 如果您的类型集有限,则可能需要将类型列枚举 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)

使用单独的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)

从表格中选择DISTINCT风格1,风格2,风格3

描述

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM