Das ist zum Spaß, richtig?
Bei SQL dreht sich alles um die Verarbeitung von Sätzen von Zeilen. Wenn wir also ein 'Wort' in einen Satz von Zeichen als Zeilen umwandeln können, können wir die 'Gruppen'-Funktionen verwenden, um nützliche Dinge zu tun.
Die Verwendung einer „relationalen Datenbank-Engine“ zur einfachen Zeichenmanipulation fühlt sich falsch an. Ist es dennoch möglich, Ihre Frage nur mit SQL zu beantworten? Ja, das ist es...
Jetzt habe ich immer eine Tabelle, die eine ganzzahlige Spalte mit etwa 500 Zeilen enthält, die die aufsteigende Folge 1 .. 500 hat. Sie wird "Integerseries" genannt. Es ist eine wirklich kleine Tabelle, die viel verbraucht hat, sodass sie im Speicher zwischengespeichert wird. Es soll den from 'select 1 ... union ...
ersetzen Text in Abfragen.
Es ist nützlich, um aufeinanderfolgende Zeilen (eine Tabelle) von allem zu generieren, was Sie berechnen können, das auf einer Ganzzahl basiert, indem Sie es in einem cross join
verwenden (auch jeder inner join
). Ich verwende es zum Generieren von Tagen für ein Jahr, zum Analysieren von durch Kommas getrennten Zeichenfolgen usw.
Nun, die sql mid
Funktion kann verwendet werden, um das Zeichen an einer bestimmten Position zurückzugeben. Durch die Verwendung der 'Integerseries'-Tabelle kann ich ein 'Wort' 'einfach' in eine Zeichentabelle mit einer Zeile pro Zeichen umwandeln. Dann nutzen Sie die 'Gruppen'-Funktionen...
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
Ausgabe:
charAtIdx count(charAtIdx)
--------- ------------------
1
d 1
e 1
H 1
l 3
o 2
r 1
W 1
Hinweis:Die Anzahl der Zeilen in der Ausgabe ist die Anzahl der verschiedenen Zeichen in der Zeichenfolge. Wenn also die Anzahl der ausgegebenen Zeilen gezählt wird, ist die Anzahl der 'verschiedenen Buchstaben' bekannt.
Diese Beobachtung wird in der letzten Abfrage verwendet.
Die letzte Abfrage:
Der interessante Punkt hier ist, die 'Integerseries'-'Cross Join'-Beschränkungen (1 .. Länge(Wort)) in den eigentlichen 'Join' zu verschieben, anstatt es im where
zu tun Klausel. Dies liefert dem Optimierer Hinweise, wie er die beim join
erzeugten Daten einschränken kann .
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
Ausgabe:
wordId word letterCount
------ -------------------- -------------
1 3333333333 1
2 1113333333 2
3 1112222444 3
4 Hello World 8
5 funny - not so much? 13
Worttabelle und Daten:
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-Tabelle:Bereich 1 .. 30 für dieses Beispiel.
CREATE TABLE `integerseries` (
`id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=500 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci