Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

MySql PHP chọn số lượng các giá trị khác biệt từ dữ liệu được phân tách bằng dấu phẩy (thẻ)

Giải pháp

Tôi thực sự không biết cách chuyển danh sách ngang các giá trị được phân tách bằng dấu phẩy thành danh sách các hàng mà không cần tạo bảng chứa số, vì bạn có thể có nhiều số nhất có thể có các giá trị được phân tách bằng dấu phẩy. Nếu bạn có thể tạo bảng này, đây là câu trả lời của tôi:

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;

Lợi nhuận:

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

Xem sqlfiddle

Giải thích

Tình huống

  1. Chúng tôi nối tất cả các thẻ bằng dấu phẩy để chỉ tạo một danh sách các thẻ thay vì một thẻ trên mỗi hàng
  2. Chúng tôi đếm xem chúng tôi có bao nhiêu thẻ trong danh sách của mình
  3. Chúng tôi tìm cách có thể nhận được một giá trị trong danh sách này
  4. Chúng tôi tìm cách có thể nhận được tất cả các giá trị dưới dạng các hàng riêng biệt
  5. Chúng tôi đếm các thẻ được nhóm theo giá trị của chúng

Ngữ cảnh

Hãy xây dựng lược đồ của bạn:

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

Nối tất cả danh sách các thẻ

Chúng tôi sẽ làm việc với tất cả các thẻ trong một dòng, vì vậy chúng tôi sử dụng GROUP_CONCAT để thực hiện công việc:

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

Trả về tất cả các thẻ được phân tách bằng dấu phẩy:

Đếm tất cả các thẻ

Để đếm tất cả các thẻ, chúng tôi lấy độ dài của danh sách đầy đủ các thẻ và chúng tôi xóa độ dài của danh sách đầy đủ các thẻ sau khi thay thế , bởi không có gì. Chúng tôi thêm 1, vì dấu phân cách giữa hai giá trị.

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

Lợi nhuận:

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

Lấy thẻ thứ N trong danh sách thẻ

Chúng tôi sử dụng SUBSTRING_INDEX chức năng lấy

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

Với logic như vậy, để có thẻ thứ 3 trong danh sách của chúng tôi, chúng tôi sử dụng:

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

Lợi nhuận:

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

Nhận tất cả các giá trị dưới dạng các hàng riêng biệt

Ý tưởng của tôi hơi phức tạp:

  1. Tôi biết chúng ta có thể tạo các hàng bằng cách nối các bảng
  2. Tôi cần lấy thẻ thứ N trong danh sách bằng cách sử dụng yêu cầu ở trên

Vì vậy, chúng tôi sẽ tạo một bảng chứa tất cả các số từ 1 đến số thẻ tối đa mà bạn có thể có trong danh sách của mình. Nếu bạn có thể có giá trị 1M, hãy tạo 1M mục nhập từ 1 đến 1.000.000. Đối với 100 thẻ, đây sẽ là:

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

Bây giờ, chúng ta nhận được num th (num là một hàng trong number ) bằng cách sử dụng truy vấn sau:

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

Lợi nhuận:

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

Đếm số lần xuất hiện thẻ

Ngay sau khi chúng tôi có cổ điển hàng, chúng tôi có thể dễ dàng đếm số lần xuất hiện của mỗi thẻ.

Xem phần đầu của câu trả lời này để xem yêu cầu.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chuyển đổi tập lệnh MySQL sang H2

  2. Thời gian bắt đầu MySQL chậm ở chế độ GTID? Kích thước tệp nhật ký nhị phân có thể là vấn đề

  3. Cách di chuyển MySQL từ Amazon EC2 sang Trung tâm dữ liệu tại chỗ của bạn mà không có thời gian ngừng hoạt động

  4. biến được xác định toàn cầu tùy chỉnh mysql

  5. Cách đơn giản nhất để chèn ngày trống trong kết quả sql (trên mysql hoặc perl end) là gì?