![](/img/trans.png)
[英]Select DISTINCT from multiple columns of multiple tables with PHP and MySQL
[英]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 distance或SOUNDS LIKE
),如果发现任何类似类型,则询问用户是否要用其中一种替换该类型被找到或保留原始类型(并将其添加到类型列表)。
这是第一种情况下的数据(两个表Songs
和SongGenres
):
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.