Intereting Posts

Как выбрать отдельные значения из нескольких столбцов mysql и поместить их в один массив PHP?

У меня есть таблица для песен, где каждая песня может содержать до 3-х разных жанров. Поэтому в моей таблице для каждой песни у меня есть жанр жанра1, жанр2 и жанр3. Я пытаюсь отобразить все жанры, доступные в списке.

Вот случайный пример:

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» может быть подано в разделе «Блюз» и «Delta Blues», но это все), и искусственное ограничение (на английском языке A3's acid house house) приходит на ум 3 жанра на песню. Если у вас ограниченный набор жанров, вы можете захотеть перечислить колонку жанра. Таблица 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. Потенциальным недостатком является то, что он ограничивает допустимые жанры тем, что указаны в таблице. Разумеется, имеет смысл предоставить учетные записи пользователей, у которых есть привилегии INSERT на SongGenres, поэтому это ограничение не является серьезным. После того, как вы начнете добавлять новые жанры, вы столкнулись с той же проблемой, что и при отсутствии таблиц жанров: опечатки. Вместо добавления новых жанров, которые не найдены в таблице жанров, ищите похожие (используя, например, расстояние SOUNDS LIKE или SOUNDS LIKE ), и, если они есть, спросите пользователя, хотят ли они заменить жанр одним из был найден или сохранился оригинальный жанр (и добавьте его в список жанров).

Вот как выглядели бы данные в первом случае (две таблицы, Songs и SongGenres ):

  mysql> SELECT * FROM Songs;
 + ---- + --------------------- + -------- + ----
 |  id |  название |  художник |  ...
 + ---- + --------------------- + -------- + ----
 |  1 |  Кросс-роуд блюз |  ...
 |  2 |  Мир в долине |  ...   
 + ---- + --------------------- + -------- + ----
 2 ряда в наборе (0,00 сек)

 mysql> SELECT * FROM SongGenres;
 + ------ + ------------- +
 |  песня |  жанр |
 + ------ + ------------- +
 |  2 |  кислота |
 |  1 |  блюз |
 |  2 |  страна |
 |  1 |  дельта-блюз |
 |  2 |  Евангелие |
 |  2 |  дом |
 |  2 |  техно |
 + ------ + ------------- +
 7 строк в наборе (0,00 сек)

 mysql> SELECT s.title, sg.genre FROM Songs AS s JOIN SongGenres AS sg ON s.id = sg.song;
 + --------------------- + ------------- +
 |  название |  жанр |
 + --------------------- + ------------- +
 |  Кросс-роуд блюз |  блюз |
 |  Кросс-роуд блюз |  дельта-блюз |
 |  Мир в долине |  кислота |
 |  Мир в долине |  страна |
 |  Мир в долине |  Евангелие |
 |  Мир в долине |  дом |
 |  Мир в долине |  техно |
 + --------------------- + ------------- +
 7 строк в наборе (0,00 сек)

В отдельной таблице Genres данные в Songs будут выглядеть одинаково, но в других таблицах у нас будет что-то вроде:

  mysql> SELECT * FROM Жанры;
 + ---- + ------------- +
 |  id |  имя |
 + ---- + ------------- +
 |  1 |  кислота |
 |  2 |  блюз |
 |  3 |  классический |
 |  4 |  страна |
 |  5 |  дельта-блюз |
 |  6 |  народные |
 |  7 |  Евангелие |
 |  8 |  хип-хоп |
 |  9 |  дом |
 ...
 |  18 |  техно |
 + ---- + ------------- +
 18 строк в наборе (0,00 сек)

 mysql> SELECT * FROM SongGenres;
 + ------ + ------- +
 |  песня |  жанр |
 + ------ + ------- +
 |  1 |  2 |
 |  1 |  5 |
 |  2 |  1 |
 |  2 |  4 |
 |  2 |  7 |
 |  2 |  9 |
 |  2 |  18 |
 + ------ + ------- +
 7 строк в наборе (0,00 сек)

 mysql> SELECT s.title, g.name AS жанр
     -> От песен AS s 
     -> JOIN SongGenres AS sg ON s.id = sg.song 
     -> JOIN Жанры AS g ON sg.genre = g.id;
 + --------------------- + ------------- +
 |  название |  жанр |
 + --------------------- + ------------- +
 |  Кросс-роуд блюз |  блюз |
 |  Кросс-роуд блюз |  дельта-блюз |
 |  Мир в долине |  кислота |
 |  Мир в долине |  страна |
 |  Мир в долине |  Евангелие |
 |  Мир в долине |  дом |
 |  Мир в долине |  техно |
 + --------------------- + ------------- +
 7 строк в наборе (0,00 сек)

SELECT DISTINCT genre1, genre2, жанр3 FROM tabel

Описание

Возможно, вам нужен лучший дизайн базы данных … songs | genres | [song_id|genre_id] songs | genres | [song_id|genre_id]