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

Policz liczbę unikalnych znaków w ciągu

To dla zabawy, prawda?

SQL polega na przetwarzaniu zestawów wierszy, więc jeśli możemy przekonwertować „słowo” na zestaw znaków jako wiersze, możemy użyć funkcji „grupy”, aby zrobić przydatne rzeczy.

Używanie „silnika relacyjnej bazy danych” do wykonywania prostych manipulacji znakami wydaje się niewłaściwe. Czy jednak można odpowiedzieć na twoje pytanie za pomocą samego SQL? Tak, to jest...

Teraz zawsze mam tabelę, która ma jedną kolumnę liczb całkowitych, która ma około 500 wierszy i ma kolejność rosnącą od 1 do 500. Nazywa się to „seriami całkowitymi”. Jest to naprawdę mały stół, który dużo używał, więc jest buforowany w pamięci. Został zaprojektowany w celu zastąpienia from 'select 1 ... union ... tekst w zapytaniach.

Przydaje się do generowania kolejnych wierszy (tabeli) wszystkiego, co można obliczyć na podstawie liczby całkowitej, używając jej w cross join (także dowolne inner join ). Używam go do generowania dni przez rok, analizowania ciągów oddzielonych przecinkami itp.

Teraz sql mid funkcja może być użyta do zwrócenia znaku na danej pozycji. Używając tabeli „całkowite” mogę „łatwo” przekonwertować „słowo” na tabelę znaków z jednym wierszem na znak. Następnie użyj funkcji 'grupy'...

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  

Wyjście:

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

Uwaga:Liczba wierszy w danych wyjściowych to liczba różnych znaków w ciągu. Tak więc, jeśli policzona zostanie liczba wierszy wyjściowych, to liczba „różnych liter” będzie znana.

Ta obserwacja jest używana w ostatecznym zapytaniu.

Ostateczne zapytanie:

Interesującym punktem jest przeniesienie ograniczeń 'łączenia krzyżowego' 'integereries' (1 .. length(word)) do rzeczywistego 'join' zamiast robienia tego w where klauzula. Daje to optymalizatorowi wskazówki, jak ograniczyć dane generowane podczas wykonywania 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  

Wyjście:

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

Tabela słów i dane:

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

Tabela szeregów całkowitych:zakres 1 .. 30 dla tego przykładu.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Niezwykle podstawowy PHP i Mysql

  2. PHP i MYSQL:używanie grupowania według kategorii

  3. Przechowywanie zawartości tablicy PHP w bazie danych MySQL

  4. Schemat bazy danych systemu wiadomości

  5. Jak uzyskać łączną liczbę użytkowników dziennie w MySQL?