在MySQL中提取字段名稱以及更新前后數(shù)據(jù)

這兩天在工作中碰到一個需求纳令,開發(fā)那邊希望在做增量數(shù)據(jù)的時候饼齿,能夠得到被更新的字段名以及該字段被更新前后的數(shù)據(jù)屡萤,然后在實(shí)現(xiàn)的過程中锈死,用到了兩個之前沒有看到過的函數(shù):FIND_IN_SET()和SUBSTRING_INDEX()贫堰。
一、函數(shù)的用法
1待牵、FIND_IN_SET(str,strlist)其屏,其中,str是要查找的字符串(可以是字符串也可以是字段)缨该,strlist是用逗號分隔的字符串(可以是字符串也可以是字段)偎行;假設(shè)str包含在strlist中,則返回str在strlist中第一次出現(xiàn)的位置(位置從1開始)贰拿,如果不包含蛤袒,則返回0。
1.1 str和strlist都是字符串
比如:

SELECT 
FIND_IN_SET('a','c,d,a,d,a,v')
FROM db1.`test_instr`

返回3膨更,第一個'a'在字符串'c,d,a,d,a,v'中在第3的位置妙真。

SELECT 
FIND_IN_SET('e','c,d,a,d,a,v')
FROM db1.`test_instr`

返回0,'e'在'c,d,a,d,a,v' 中不存在
特殊情況:
-- 當(dāng)str或者strlist中任意一個為NULL時荚守,返回NULL

SELECT 
FIND_IN_SET(NULL,'c,d,a,d,a,v')
FROM db1.`test_instr`
-- 
SELECT 
FIND_IN_SET('e',NULL)
FROM db1.`test_instr`
--
SELECT 
FIND_IN_SET(NULL,NULL)
FROM db1.`test_instr`

上面三條查詢均返回NULL
-- 當(dāng)str或者strlist中任意一個為空字符串時珍德,返回0
比如

SELECT *,
FIND_IN_SET('','') 
FROM instr_test_left
-- 
SELECT *,
FIND_IN_SET('','a,b,c') 
FROM instr_test_left
-- 
SELECT *,
FIND_IN_SET('a','') 
FROM instr_test_left

上面三條查詢均返回0

注:练般,參數(shù)str中不能帶逗號,如果帶逗號锈候,函數(shù)會不起作用薄料,
比如

SELECT 
FIND_IN_SET('c,d','c,d,a,d,a,v')
FROM db1.`test_instr`

返回0,函數(shù)認(rèn)為'c,d'在'c,d,a,d,a,v'中不存在泵琳,但是看起來又似乎是存在的摄职。
1.2 str和strlist為字段

  • 兩個都是字段:每條記錄的str和strlist進(jìn)行比較
SELECT *,
FIND_IN_SET(str,strlist)

FROM instr_test_left

返回


image.png

-- str是字段,strlist是字符串:str字段的每個值和strlist作比較

SELECT str,'k,a,d,d,p,b,f',
FIND_IN_SET(str,'k,a,d,d,p,b,f')

FROM instr_test_left

同理获列,str是字符串谷市,strlist是段:str和strlist的每個值作比較。
2蛛倦、SUBSTRING_INDEX(str,delim,count)歌懒,其中,str為被截取字段溯壶,delim為關(guān)鍵字及皂,count為關(guān)鍵字出現(xiàn)的次數(shù)(count可以是負(fù)數(shù),此時從后往前數(shù))且改。用來在str中截取第count個關(guān)鍵字之前的所有字符验烧。
比如:
-- count是正數(shù)時

SELECT 
*,
SUBSTRING_INDEX(strlist,',',2)

FROM instr_test_left

返回


image.png

上面的查詢用來截取strlist中第二個逗號之前的所有字符,當(dāng)字符串中的逗號個數(shù)小于2時又跛,返回原數(shù)據(jù)(比如最后一條記錄e碍拆,返回的還是e)。
-- count是負(fù)數(shù)時

SELECT 
*,
SUBSTRING_INDEX(strlist,',',-3)

FROM instr_test_left

返回


image.png

上面的查詢用來截取strlist倒數(shù)第三個逗號之后的所有字符慨蓝,當(dāng)字符串中的逗號個數(shù)小于3時感混,返回原數(shù)據(jù)。
二礼烈、實(shí)現(xiàn)流程
假設(shè)現(xiàn)在的目標(biāo)表test_instr如下(主鍵是id)


image.png

要更新到目標(biāo)表中的數(shù)據(jù)test_instr_2如下(主鍵是id)


image.png

大體的思路如下:
1弧满、當(dāng)主鍵匹配上時才做更新操作,需要收集更新信息(匹配不上的做新增)此熬;
2庭呜、將目標(biāo)表test_instr除主鍵id外,進(jìn)行列轉(zhuǎn)行操作犀忱,列名所在列為UPDATE_FIELD募谎,值所在列為OLD_VALUE;
3阴汇、將待更新數(shù)據(jù)test_instr_2中除主鍵id外数冬,剩余字段值用逗號分隔,合并成一列CONCAT_VALUE搀庶,同時將所有列名也用逗號分隔吉执,合并成一列CONCAT_COLUMN疯淫;
4地来、利用函數(shù)find_in_set戳玫,OLD_VALUE和CONCAT_VALUE分別為參數(shù)str和strlist,當(dāng)返回值為0時未斑,表示發(fā)生了更新咕宿,提取CONCAT_VALUE中相應(yīng)的值(根據(jù)更新的字段名稱)作為NEW_VALUE。
具體實(shí)現(xiàn)如下:
MySQL中的列轉(zhuǎn)行

SELECT 
a.ID,'cate' UPDATE_FIELD, a.`cate` OLD_VALUE
FROM test_instr a
UNION ALL
SELECT 
a.ID,'uuc' UPDATE_FIELD, a.`uuc` OLD_VALUE
FROM test_instr a
UNION ALL
SELECT 
a.ID,'duc' UPDATE_FIELD, a.`duc` OLD_VALUE
FROM test_instr a

返回


image.png

test_instr_2表合并字段操作

SELECT 
a.`id` ID_B,
-- 將需要比較的字段值用逗號連接
CONCAT(a.`cate`,',',a.`uuc`,',',a.`duc`) CONCAT_VALUE,
-- 將所有列名用逗號連接
(SELECT GROUP_CONCAT(COLUMN_NAME SEPARATOR ",") FROM information_schema.COLUMNS 
WHERE TABLE_SCHEMA = 'db1' AND TABLE_NAME = 'test_instr_2') CONCAT_COLUMN
FROM test_instr_2 a

返回


image.png

利用find_in_set()函數(shù)得到更新的數(shù)據(jù)蜡秽,通過

SELECT 'TEST_INSTR' TABLE_NAME,c.ID ,c.UPDATE_FIELD,c.OLD_VALUE,
SUBSTRING_INDEX( SUBSTRING_INDEX( d.CONCAT_VALUE, ',', FIND_IN_SET(c.UPDATE_FIELD,d.CONCAT_COLUMN)-1 ), ',',- 1 ) NEW_VALUE,
SYSDATE() UPDATE_TIME
FROM
-- 列轉(zhuǎn)行
(
SELECT 
a.ID,'cate' UPDATE_FIELD, a.`cate` OLD_VALUE
FROM test_instr a
UNION ALL
SELECT 
a.ID,'uuc' UPDATE_FIELD, a.`uuc` OLD_VALUE
FROM test_instr a
UNION ALL
SELECT 
a.ID,'duc' UPDATE_FIELD, a.`duc` OLD_VALUE
FROM test_instr a
) c
INNER JOIN
(SELECT 
a.`id` ID_B,
-- 將需要比較的字段值用逗號連接
CONCAT(a.`cate`,',',a.`uuc`,',',a.`duc`) CONCAT_VALUE,
-- 將所有列名用逗號連接
(SELECT GROUP_CONCAT(COLUMN_NAME SEPARATOR ",") FROM information_schema.COLUMNS 
WHERE TABLE_SCHEMA = 'db1' AND TABLE_NAME = 'test_instr_2') CONCAT_COLUMN
FROM test_instr_2 a) d
ON c.ID=d.ID_B
AND FIND_IN_SET(c.OLD_VALUE ,d.CONCAT_VALUE )=0
AND
(c.OLD_VALUE <> ''
or d.CONCAT_VALUE <> '');

返回


image.png

這里加了一個條件FIND_IN_SET中的兩個參數(shù)不同時為空(至少有一個不為空)府阀,如果兩個參數(shù)都為空的話,F(xiàn)IND_IN_SET也會返回0芽突,但實(shí)際上空到空不算做更新试浙。
但是,現(xiàn)在有個問題:
列轉(zhuǎn)行和合并字段值寞蚌,需要把除主鍵以外的所有字段都列出來田巴,實(shí)際業(yè)務(wù)中有的表字段非常多,全部列出來的話工作量很大挟秤,我考慮利用kettle將列轉(zhuǎn)行和合并字段值的數(shù)據(jù)分別存到新表壹哺,用新表操作,但是這樣的話每張表就要對應(yīng)一個流程艘刚,有多少張表就要建立多少個流程管宵,很繁瑣,如果有好的方法希望大家多多指教攀甚!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末箩朴,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子秋度,更是在濱河造成了極大的恐慌炸庞,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件静陈,死亡現(xiàn)場離奇詭異燕雁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鲸拥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門拐格,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人刑赶,你說我怎么就攤上這事捏浊。” “怎么了撞叨?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵金踪,是天一觀的道長浊洞。 經(jīng)常有香客問我,道長胡岔,這世上最難降的妖魔是什么法希? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮靶瘸,結(jié)果婚禮上苫亦,老公的妹妹穿的比我還像新娘。我一直安慰自己怨咪,他們只是感情好屋剑,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诗眨,像睡著了一般唉匾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上匠楚,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天巍膘,我揣著相機(jī)與錄音,去河邊找鬼油啤。 笑死典徘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的益咬。 我是一名探鬼主播逮诲,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼幽告!你這毒婦竟也來了梅鹦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤冗锁,失蹤者是張志新(化名)和其女友劉穎齐唆,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冻河,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡箍邮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了叨叙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锭弊。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖擂错,靈堂內(nèi)的尸體忽然破棺而出味滞,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布剑鞍,位于F島的核電站昨凡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蚁署。R本人自食惡果不足惜便脊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望形用。 院中可真熱鬧就轧,春花似錦、人聲如沸田度。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镇饺。三九已至,卻和暖如春送讲,著一層夾襖步出監(jiān)牢的瞬間奸笤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工哼鬓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留监右,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓异希,卻偏偏與公主長得像健盒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子称簿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350