sql >> Database teknologi >  >> RDS >> Mysql

Tæl antallet af unikke tegn i en streng

Det er for sjov ikke?

SQL handler om at behandle sæt af rækker, så hvis vi kan konvertere et 'ord' til et sæt tegn som rækker, så kan vi bruge 'gruppe'-funktionerne til at lave nyttige ting.

At bruge en 'relationel databasemotor' til at lave simpel karaktermanipulation føles forkert. Er det stadig muligt at besvare dit spørgsmål med kun SQL? Ja det er...

Nu har jeg altid en tabel, der har en heltalskolonne, der har omkring 500 rækker i den, der har den stigende rækkefølge 1 .. 500. Det kaldes 'heltalsserier'. Det er en rigtig lille tabel, der har brugt meget, så den bliver cachelagret i hukommelsen. Den er designet til at erstatte from 'select 1 ... union ... tekst i forespørgsler.

Det er nyttigt til at generere sekventielle rækker (en tabel) af alt, som du kan beregne, der er baseret på et heltal ved at bruge det i en cross join (også enhver inner join ). Jeg bruger den til at generere dage i et år, parsing af kommaseparerede strenge osv.

Nu, sql mid funktion kan bruges til at returnere tegnet på en given position. Ved at bruge 'integerseries'-tabellen kan jeg 'let' konvertere et 'ord' til en tegntabel med en række pr. tegn. Brug derefter 'gruppe'-funktionerne...

SET @word='Hello World';

SELECT charAtIdx, COUNT(charAtIdx)
FROM (SELECT charIdx.id,
    MID(@word, charIdx.id, 1) AS charAtIdx 
    FROM integerseries AS charIdx
    WHERE charIdx.id <= LENGTH(@word)
    ORDER BY charIdx.id ASC
    ) wordLetters
GROUP BY
   wordLetters.charAtIdx
ORDER BY charAtIdx ASC  
 

Output:

charAtIdx  count(charAtIdx)  
---------  ------------------
                            1
d                           1
e                           1
H                           1
l                           3
o                           2
r                           1
W                           1
 

Bemærk:Antallet af rækker i outputtet er antallet af forskellige tegn i strengen. Så hvis antallet af outputrækker tælles, vil antallet af 'forskellige bogstaver' være kendt.

Denne observation bruges i den endelige forespørgsel.

Den sidste forespørgsel:

Det interessante her er at flytte 'integerseries' 'cross join'-begrænsningerne (1 .. length(word)) ind i den faktiske 'join' i stedet for at gøre det i where klausul. Dette giver optimeringsværktøjet ledetråde til, hvordan man begrænser de data, der produceres, når du udfører join .

SELECT wordLetterCounts.wordId, wordLetterCounts.word, COUNT(wordLetterCounts.wordId) AS letterCount FROM (SELECT words.id AS wordId, words.word AS word, iseq.id AS charPos, MID(words.word, iseq.id, 1) AS charAtPos, COUNT(MID(words.word, iseq.id, 1)) AS charAtPosCount FROM words JOIN integerseries AS iseq ON iseq.id BETWEEN 1 AND words.wordlen GROUP BY words.id, MID(words.word, iseq.id, 1) ) AS wordLetterCounts GROUP BY wordLetterCounts.wordId

Output:

wordId  word                  letterCount  
------  --------------------  -------------
     1  3333333333                        1
     2  1113333333                        2
     3  1112222444                        3
     4  Hello World                       8
     5  funny - not so much?             13
 

Ordtabel og data:

CREATE TABLE `words` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `word` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,
  `wordlen` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

/*Data for the table `words` */

insert  into `words`(`id`,`word`,`wordlen`) values (1,'3333333333',10);
insert  into `words`(`id`,`word`,`wordlen`) values (2,'1113333333',10);
insert  into `words`(`id`,`word`,`wordlen`) values (3,'1112222444',10);
insert  into `words`(`id`,`word`,`wordlen`) values (4,'Hello World',11);
insert  into `words`(`id`,`word`,`wordlen`) values (5,'funny - not so much?',20);
 

Integerseries tabel:interval 1 .. 30 for dette eksempel.

CREATE TABLE `integerseries` (
  `id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=500 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
 


  1. Oracle Rows to Column Transformation

  2. Rekursiv MySQL-forespørgsel med relationel innoDB

  3. hvor skal jeg placere installationsressourcer (wxs-fil, dmg-script, ikon) og hvordan man konfigurerer maven antrun, når jeg implementerer selvstændig app

  4. World Backup Day:Hvordan og hvornår skal du sikkerhedskopiere din database?