Mysql
 sql >> Baza danych >  >> RDS >> Mysql

MySql PHP wybierz liczbę odrębnych wartości z danych oddzielonych przecinkami (tagi)

Rozwiązanie

Naprawdę nie wiem, jak przekształcić poziomą listę wartości oddzielonych przecinkami w listę wierszy bez tworzenia tabeli zawierającej liczby, tyle liczb, ile możesz mieć wartości oddzielonych przecinkami. Jeśli możesz stworzyć tę tabelę, oto moja odpowiedź:

SELECT 
  SUBSTRING_INDEX(SUBSTRING_INDEX(all_tags, ',', num), ',', -1) AS one_tag,
  COUNT(*) AS cnt
FROM (
  SELECT
    GROUP_CONCAT(tags separator ',') AS all_tags,
    LENGTH(GROUP_CONCAT(tags SEPARATOR ',')) - LENGTH(REPLACE(GROUP_CONCAT(tags SEPARATOR ','), ',', '')) + 1 AS count_tags
  FROM test
) t
JOIN numbers n
ON n.num <= t.count_tags
GROUP BY one_tag
ORDER BY cnt DESC;

Zwroty:

+---------------------+-----+
| one_tag             | cnt |
+---------------------+-----+
| chicken             |   5 |
| pork                |   4 |
| spaghetti           |   3 |
| fried-rice          |   2 |
| manchurain          |   2 |
| pho                 |   1 |
| chicken-calzone     |   1 |
| fettuccine          |   1 |
| chorizo             |   1 |
| meat-balls          |   1 |
| miso-soup           |   1 |
| chanko-nabe         |   1 |
| chicken-manchurian  |   1 |
| pork-manchurian     |   1 |
| sweet-and-sour-pork |   1 |
| peking-duck         |   1 |
| duck                |   1 |
+---------------------+-----+
17 rows in set (0.01 sec)

Zobacz sqlfiddle

Wyjaśnienie

Scenariusz

  1. Łączymy wszystkie tagi za pomocą przecinka, aby utworzyć tylko jedną listę tagów zamiast jednego na wiersz
  2. Liczymy, ile tagów mamy na naszej liście
  3. Dowiadujemy się, jak możemy uzyskać jedną wartość z tej listy
  4. Dowiadujemy się, jak możemy uzyskać wszystkie wartości jako odrębne wiersze
  5. Liczymy tagi pogrupowane według ich wartości

Kontekst

Zbudujmy Twój schemat:

CREATE TABLE test (
    id INT PRIMARY KEY,
    tags VARCHAR(255)
);

INSERT INTO test VALUES
    ("1",         "pho,pork"),
    ("2",         "fried-rice,chicken"),
    ("3",         "fried-rice,pork"),
    ("4",         "chicken-calzone,chicken"),
    ("5",         "fettuccine,chicken"),
    ("6",         "spaghetti,chicken"),
    ("7",         "spaghetti,chorizo"),
    ("8",         "spaghetti,meat-balls"),
    ("9",         "miso-soup"),
    ("10",        "chanko-nabe"),
    ("11",        "chicken-manchurian,chicken,manchurain"),
    ("12",        "pork-manchurian,pork,manchurain"),
    ("13",        "sweet-and-sour-pork,pork"),
    ("14",        "peking-duck,duck");

Połącz całą listę tagów

Będziemy pracować ze wszystkimi tagami w jednej linii, więc używamy GROUP_CONCAT wykonać pracę:

SELECT GROUP_CONCAT(tags SEPARATOR ',') FROM test;

Zwraca wszystkie tagi oddzielone przecinkiem:

Policz wszystkie tagi

Aby policzyć wszystkie tagi, otrzymujemy długość pełnej listy tagów i usuwamy długość pełnej listy tagów po zastąpieniu , przez nic. Dodajemy 1, ponieważ separator znajduje się między dwiema wartościami.

SELECT LENGTH(GROUP_CONCAT(tags SEPARATOR ',')) - LENGTH(REPLACE(GROUP_CONCAT(tags SEPARATOR ','), ',', '')) + 1 AS count_tags
FROM test;

Zwroty:

+------------+
| count_tags |
+------------+
|         28 |
+------------+
1 row in set (0.00 sec)

Pobierz N-ty tag na liście tagów

Używamy SUBSTRING_INDEX funkcja, aby uzyskać

-- returns the string until the 2nd delimiter\'s occurrence from left to right: a,b
SELECT SUBSTRING_INDEX('a,b,c', ',', 2);

-- return the string until the 1st delimiter, from right to left: c
SELECT SUBSTRING_INDEX('a,b,c', ',', -1);

-- we need both to get: b (with 2 being the tag number)
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('a,b,c', ',', 2), ',', -1);

Przy takiej logice, aby uzyskać trzeci tag na naszej liście, używamy:

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(tags SEPARATOR ','), ',', 3), ',', -1)
FROM test;

Zwroty:

+-------------------------------------------------------------------------------------+
| SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(tags SEPARATOR ','), ',', 3), ',', -1) |
+-------------------------------------------------------------------------------------+
| fried-rice                                                                          |
+-------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

Pobierz wszystkie wartości jako odrębne wiersze

Mój pomysł jest trochę skomplikowany:

  1. Wiem, że możemy tworzyć wiersze, łącząc tabele
  2. Muszę uzyskać N-ty tag na liście, korzystając z powyższego żądania

Stworzymy więc tabelę zawierającą wszystkie liczby od 1 do maksymalnej liczby tagów, które możesz mieć na swojej liście. Jeśli możesz mieć wartości 1M, utwórz 1M wpisów od 1 do 1 000 000. Dla 100 tagów będzie to:

CREATE TABLE numbers (
  num INT PRIMARY KEY
);

INSERT INTO numbers VALUES
    ( 1 ), ( 2 ), ( 3 ), ( 4 ), ( 5 ), ( 6 ), ( 7 ), ( 8 ), ( 9 ), ( 10 ), 
    ( 11 ), ( 12 ), ( 13 ), ( 14 ), ( 15 ), ( 16 ), ( 17 ), ( 18 ), ( 19 ), ( 20 ), 
    ( 21 ), ( 22 ), ( 23 ), ( 24 ), ( 25 ), ( 26 ), ( 27 ), ( 28 ), ( 29 ), ( 30 ), 
    ( 31 ), ( 32 ), ( 33 ), ( 34 ), ( 35 ), ( 36 ), ( 37 ), ( 38 ), ( 39 ), ( 40 ), 
    ( 41 ), ( 42 ), ( 43 ), ( 44 ), ( 45 ), ( 46 ), ( 47 ), ( 48 ), ( 49 ), ( 50 ), 
    ( 51 ), ( 52 ), ( 53 ), ( 54 ), ( 55 ), ( 56 ), ( 57 ), ( 58 ), ( 59 ), ( 60 ), 
    ( 61 ), ( 62 ), ( 63 ), ( 64 ), ( 65 ), ( 66 ), ( 67 ), ( 68 ), ( 69 ), ( 70 ), 
    ( 71 ), ( 72 ), ( 73 ), ( 74 ), ( 75 ), ( 76 ), ( 77 ), ( 78 ), ( 79 ), ( 80 ), 
    ( 81 ), ( 82 ), ( 83 ), ( 84 ), ( 85 ), ( 86 ), ( 87 ), ( 88 ), ( 89 ), ( 90 ), 
    ( 91 ), ( 92 ), ( 93 ), ( 94 ), ( 95 ), ( 96 ), ( 97 ), ( 98 ), ( 99 ), ( 100 );

Teraz otrzymujemy num th (liczba jest wierszem w number ) za pomocą następującego zapytania:

SELECT n.num, SUBSTRING_INDEX(SUBSTRING_INDEX(all_tags, ',', num), ',', -1) as one_tag
FROM (
  SELECT
    GROUP_CONCAT(tags SEPARATOR ',') AS all_tags,
    LENGTH(GROUP_CONCAT(tags SEPARATOR ',')) - LENGTH(REPLACE(GROUP_CONCAT(tags SEPARATOR ','), ',', '')) + 1 AS count_tags
  FROM test
) t
JOIN numbers n
ON n.num <= t.count_tags

Zwroty:

+-----+---------------------+
| num | one_tag             |
+-----+---------------------+
|   1 | pho                 |
|   2 | pork                |
|   3 | fried-rice          |
|   4 | chicken             |
|   5 | fried-rice          |
|   6 | pork                |
|   7 | chicken-calzone     |
|   8 | chicken             |
|   9 | fettuccine          |
|  10 | chicken             |
|  11 | spaghetti           |
|  12 | chicken             |
|  13 | spaghetti           |
|  14 | chorizo             |
|  15 | spaghetti           |
|  16 | meat-balls          |
|  17 | miso-soup           |
|  18 | chanko-nabe         |
|  19 | chicken-manchurian  |
|  20 | chicken             |
|  21 | manchurain          |
|  22 | pork-manchurian     |
|  23 | pork                |
|  24 | manchurain          |
|  25 | sweet-and-sour-pork |
|  26 | pork                |
|  27 | peking-duck         |
|  28 | duck                |
+-----+---------------------+
28 rows in set (0.01 sec)

Policz wystąpienia tagów

Jak tylko mamy teraz klasyczny wierszy, możemy łatwo policzyć wystąpienia każdego tagu.

Zobacz górę tej odpowiedzi aby zobaczyć prośbę.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak utworzyć i wstawić obiekt JSON za pomocą zapytań MySQL?

  2. Czy istnieje alternatywa ANSI SQL dla słowa kluczowego MYSQL LIMIT?

  3. Jak ograniczyć dostęp do portu MySQL

  4. MySQL/SQL:Aktualizacja ze skorelowanym podzapytaniem z samej zaktualizowanej tabeli

  5. Brak mysql.sock; otrzymując OperationalError:(2002, Nie można połączyć się z lokalnym serwerem MySQL przez gniazdo '/tmp/mysql.sock' (2))