Løsning
Jeg ved ikke rigtig, hvordan man transformerer en vandret liste med kommaseparerede værdier til en liste med rækker uden at oprette en tabel, der indeholder tal, lige så mange tal som du måske har kommaseparerede værdier. Hvis du kan oprette denne tabel, her er mit svar:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(alle_tags, ',', num), ',', -1) AS one_tag, COUNT(*) AS cntFROM ( SELECT GROUP_CONCAT(tags separator ',') AS all_tags, LENGTH (GROUP_CONCAT(tags SEPARATOR ',')) - LENGTH(REPLACE(GROUP_CONCAT(tags SEPARATOR ','), ',', '')) + 1 AS count_tags FRA test) tJOIN-tal nON n.num <=t.count_tagsGROUP BY one_tagORDER BY cnt DESC;
Returnerer:
+---------------------+-----+| one_tag | cnt |+----------------------+-----+| kylling | 5 || svinekød | 4 || spaghetti | 3 || stegte ris | 2 || manchurin | 2 || pho | 1 || kylling-calzone | 1 || fettuccine | 1 || chorizo | 1 || frikadeller | 1 || miso-suppe | 1 || chanko-nabe | 1 || kylling-manchurian | 1 || svine-manchurian | 1 || sødt-surt-svinekød | 1 || peking-and | 1 || and | 1 |+---------------------+-----+17 rækker i sæt (0,01 sek.)
Se sqlfiddle
Forklaring
Scenarie
- Vi sammenkæder alle tags ved hjælp af et komma for kun at oprette én liste med tags i stedet for én pr. række
- Vi tæller, hvor mange tags vi har på vores liste
- Vi finder, hvordan vi kan få én værdi på denne liste
- Vi finder ud af, hvordan vi kan få alle værdier som adskilte rækker
- Vi tæller tags grupperet efter deres værdi
Kontekst
Lad os bygge dit skema:
CREATE TABLE test ( id INT PRIMARY KEY, tags VARCHAR(255));INSERT INTO test VALUES ("1", "pho,pork"), ("2", "fried-rice, chicken" ), ("3", "stegte ris, svinekød"), ("4", "kylling-calzone, kylling"), ("5", "fettuccine, kylling"), ("6", "spaghetti, kylling"), ("7", "spaghetti, chorizo"), ("8", "spaghetti, frikadeller"), ("9", "miso-suppe"), ("10", "chanko- nabe"), ("11", "kylling-manchurian, kylling, manchurin"), ("12", "svine-manchurian, svinekød, manchurin"), ("13", "sød-og-surt-svinekød, svinekød"), ("14", "peking-and, and");
Sæt alle lister over tags sammen
Vi vil arbejde med alle tags på en enkelt linje, så vi bruger GROUP_CONCAT
for at udføre jobbet:
SELECT GROUP_CONCAT(tags SEPARATOR ',') FROM test;
Returnerer alle tags adskilt af et komma:
Tæl alle tags
For at tælle alle tags får vi længden af den fulde liste af tags, og vi fjerner længden af den fulde liste af tags efter at have erstattet ,
ved ingenting. Vi tilføjer 1, da separatoren er mellem to værdier.
SELECT LENGTH(GROUP_CONCAT(tags SEPARATOR ',')) - LENGTH(REPLACE(GROUP_CONCAT(tags SEPARATOR ','), ',', '')) + 1 AS count_tagsFROM test;
Returnerer:
+-------------+| count_tags |+-------------+| 28 |+------------+1 række i sæt (0,00 sek.)
Få det N. tag i taglisten
Vi bruger SUBSTRING_INDEX
funktion for at få
-- returnerer strengen indtil 2. skilletegns forekomst fra venstre mod højre:a,bSELECT SUBSTRING_INDEX('a,b,c', ',', 2);-- returner strengen indtil den 1. skilletegn, fra højre mod venstre:cSELECT SUBSTRING_INDEX('a,b,c', ',', -1);-- vi har brug for begge for at få:b (hvor 2 er tagnummeret)SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( 'a,b,c', ',', 2), ',', -1);
Med sådan logik, for at få det 3. tag på vores liste, bruger vi:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(tags SEPARATOR ','), ',', 3), ',', -1)FRA test;
Returnerer:
+------------------------------------------------ ------------------------------------------+| SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(tags SEPARATOR ','), ',', 3), ',', -1) |+--------------------------- -------------------------------------------------- --------------+| stegte ris |+----------------------------------------------------- ----------------------------------------+1 række i sæt (0,00 sek.) Få alle værdier som adskilte rækker
Min idé er lidt tricky:
- Jeg ved, at vi kan oprette rækker ved at forbinde tabeller
- Jeg har brug for at få det N. tag på listen ved hjælp af anmodningen ovenfor
Så vi opretter en tabel, der indeholder alle tal fra 1 til det maksimale antal tags, du kan have på din liste. Hvis du kan have 1 mio. værdier, skal du oprette 1 mio. poster fra 1 til 1.000.000. For 100 tags vil dette være:
OPRET TABEL numre ( num INT PRIMÆR NØGLE); INDSÆT I tal VÆRDIER ( 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 );
Nu får vi num
th (tal er en række i nummer
) ved hjælp af følgende forespørgsel:
SELECT n.num, SUBSTRING_INDEX(SUBSTRING_INDEX(alle_tags, ',', num), ',', -1) som one_tagFROM ( SELECT GROUP_CONCAT(tags SEPARATOR ',') AS all_tags, LENGTH(GROUP_CONCAT( tags SEPARATOR ',')) - LENGTH(REPLACE(GROUP_CONCAT(tags SEPARATOR ','), ',', '')) + 1 AS count_tags FRA test) tJOIN-numre ikke n.num <=t.count_tags
Returnerer:
+-----+----------------------------+| antal | one_tag |+-----+----------------------+| 1 | pho || 2 | svinekød || 3 | stegte ris || 4 | kylling || 5 | stegte ris || 6 | svinekød || 7 | kylling-calzone || 8 | kylling || 9 | fettuccine || 10 | kylling || 11 | spaghetti || 12 | kylling || 13 | spaghetti || 14 | chorizo || 15 | spaghetti || 16 | frikadeller || 17 | miso-suppe || 18 | chanko-nabe || 19 | kylling-manchurian || 20 | kylling || 21 | manchurain || 22 | svine-manchurian || 23 | svinekød || 24 | manchurin || 25 | sød-sur-flæsk || 26 | svinekød || 27 | peking-and || 28 | and |+-----+---------------------+28 rækker i sæt (0,01 sek.)
Tæl tags-forekomster
Så snart vi nu har klassisk rækker, kan vi nemt tælle forekomster af hvert tag.
Se toppen af dette svar
for at se anmodningen.