字符串分割,行轉列

使用場景

爲什麼要用到字符串分割,行轉列

  在我們開發的過程中,有時我們會遇到這樣的數據結構:

主鍵id 子集主鍵id
id children_id
122 4795/4796/4797/

  我們可以看到,在我們根據主表查詢子表中的信息時,我們從主表中獲取的子表id是以字符串的形式進行拼接的,當我們要想根據主表關聯子表信息時,我們首先將主表的子表id字段進行字符串拆分,然後將拆分後的字段行轉列,以此來關聯子表,實現子表信息的查詢操作。

字符串分割行轉列的思路

  我們在進行字符串分割行轉列的時候,我們需要用到如下兩個主要步驟:

  • 使用分隔符,實現字符串拆分操作
  • 使用循環,讓拆分後的字段實現行轉列效果

字符串分割函數

  在MySQL中,其實現字符串拆分的函數爲SUBSTRING_INDEX(str,delim,count)

關鍵字 含義
str 被拆分的字符串
delim 分隔符
count 在定界符 delim 以及count 出現前,從字符串str返回自字符串。若count爲正值,則返回最終定界符(從左邊開始)左邊的一切內容。若count爲負值,則返回定界符(從右邊開始)右邊的一切內容。

  它的用法如下:

  比如說我們想要獲取4795/4796/4797/中的4795,我們的做法是:

SELECT SUBSTRING_INDEX('4795/4796/4797/','/',1)

循環思路

  在MySQL中,一共有三種循環,分別爲whilelooprepeat,而這三種循環的使用,一般是在存儲過程之中,而這裏,由於我們所採取的並非存儲過程方法,因而在此處我們不做過多討論。

  如果我們既想要實現循環操作效果,又不想使用存儲過程,那該怎麼實現呢?

  當我們在進行字符串分割時,我們想實現的效果是,對於一個字符串,比如說4795/4796/4797/,第一次分割,我們想獲取的字符串爲4795,我們可以將其下標定義爲0,然後第二次分割,我們想獲取的字符串爲4796,我們將其下標定義爲1,以此類推,我們可以發現,通過下標的0、1、2、3…我們就可以獲取我們所要分割後的字符串數值。

  在想明白了這點之後,我們就可以發現,通過藉助第三張表,無論該表爲什麼表名,只要是其主鍵id值爲0、1、2、3…,那麼該表就可以被我們拿來做循環操作使用。

  在MySQL中,還恰恰就存在這麼一張表,就是mysql.help_topic,該表的主鍵字段help_topic_id從0開始,依次遞增,最多有634條數據,換言之,如果使用該表做循環操作,那麼理論上,其可以滿足我們絕大多數的循環操作使用場景。

字符串分割,行轉列

方法一

  在進行了上面的敘述之後,我們就可以直接上代碼了,如下:

SELECT 
    SUBSTRING_INDEX(SUBSTRING_INDEX('4795/4796/4797/','/',ht.help_topic_id+1),'/',-1) AS children_id
FROM 
    mysql.help_topic ht
WHERE 
    ht.help_topic_id < LENGTH('4795/4796/4797/')-LENGTH(REPLACE('4795/4796/4797/','/',''))

  其展示的結果爲:

children_id
4795
4796
4797

方法二

  如果我們的數據庫做了權限限制,當我們只能訪問當前數據庫時(不含mysql.help_topic),此時我們就只能自己創建一個新表,以此來替代mysql.help_topic,這裏我們創建的表爲table_for,建表語句如下:

CREATE TABLE `table_for` (
  `id` INT(11) DEFAULT NULL COMMENT 'for循環主鍵id'
) ENGINE=INNODB DEFAULT CHARSET=utf8

  在表中插入數據:

INSERT INTO table_for(id)
SELECT help_topic_id FROM mysql.help_topic ORDER BY help_topic_id ASC

  上面的插入數據源,仍然選擇的是mysql.help_topic,我們可以在本地MySQL上執行上述操作,然後將其上傳到項目所在的數據庫中,此時方法一中的sql將變成如下:

SELECT 
    SUBSTRING_INDEX(SUBSTRING_INDEX('4795/4796/4797/','/',tf.id+1),'/',-1) AS children_id
FROM 
    `table_for` tf
WHERE 
    tf.id < LENGTH('4795/4796/4797/')-LENGTH(REPLACE('4795/4796/4797/','/',''))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章