Mysql
 sql >> база данни >  >> RDS >> Mysql

Пребройте броя на уникалните знаци в низ

Това е за забавление, нали?

SQL е свързан с обработката на набори от редове, така че ако можем да преобразуваме „дума“ в набор от знаци като редове, тогава можем да използваме функциите „група“, за да правим полезни неща.

Използването на „двигател на релационна база данни“ за извършване на проста манипулация на знаци е погрешно. И все пак, възможно ли е да се отговори на въпроса ви само с SQL? Да, така е...

Сега винаги имам таблица, която има една целочислена колона, която има около 500 реда в нея, която има възходяща последователност 1 .. 500. Нарича се „целочислени серии“. Това е наистина малка таблица, която използва много, така че се кешира в паметта. Той е предназначен да замени from 'select 1 ... union ... текст в заявките.

Полезно е за генериране на последователни редове (таблица) от всичко, което можете да изчислите, което се основава на цяло число, като го използвате в cross join (също и всяко inner join ). Използвам го за генериране на дни за една година, анализиране на низове, разделени със запетая и т.н.

Сега sql mid функцията може да се използва за връщане на символа на дадена позиция. С помощта на таблицата 'integerseries' мога 'лесно' да преобразувам 'дума' в таблица със знаци с един ред на знак. След това използвайте функциите "група"...

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  

Изход:

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

Забележка:Броят на редовете в изхода е броят на различните символи в низа. Така че, ако броят на изходните редове се преброи, тогава броят на „различните букви“ ще бъде известен.

Това наблюдение се използва в крайната заявка.

Последната заявка:

Интересният момент тук е да преместите ограниченията за кръстосано присъединяване (1 .. length(word)) на 'integerseries' в действителното 'join', вместо да го правите в where клауза. Това предоставя на оптимизатора улики как да ограничи данните, произведени при извършване на 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  

Изход:

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

Таблица с думи и данни:

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

Таблица с цели серии:диапазон 1 .. 30 за този пример.

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. какво е java.io.EOFException, Съобщение:Не може да се прочете отговор от сървъра. Очаква се да прочетете 4 байта, да прочетете 0 байта

  2. PDO Множество заявки:транзакция за извършване и връщане назад

  3. Как да трансформирате вертикални данни в хоризонтални данни с SQL?

  4. Изберете всички дублиращи се редове въз основа на една или две колони?

  5. php echo първия ред изчакване/спи след това ехо втория ред