<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          注意!SQL中的NULL

          共 1241字,需瀏覽 3分鐘

           ·

          2021-01-23 03:40

          大家好,我是寶器!

          越發(fā)覺得取數(shù)之前的“預(yù)處理”非常重要,其中最核心的一點是檢查數(shù)據(jù)的準確性。大的方向有兩種,其一,確認數(shù)據(jù)本身無錯亂,其二,保障取數(shù)業(yè)務(wù)邏輯準確。

          第一種比較繁瑣、耗時,但是好處理(習(xí)慣對結(jié)果做一下統(tǒng)計值分布可以減少很多異常)。第二種不是SQL執(zhí)行過程中報錯,而是返回的結(jié)果和你需要的不太一樣。今天主要聊一下取數(shù)分析中容易忽略的點,尤其是SQL中的NULL值。

          1、空值JOIN時導(dǎo)致數(shù)據(jù)丟失

          創(chuàng)建案例數(shù)據(jù)表
          CREATE?TABLE?IF?NOT?EXISTS?tmp_test_3
          (
          id_1?INT,
          col_1?VARCHAR(255),
          col_2?VARCHAR(255)
          );


          CREATE?TABLE?IF?NOT?EXISTS?tmp_test_4
          (
          id_2?INT,
          col_3?VARCHAR(255),
          col_4?VARCHAR(255)
          );


          INSERT?INTO?tmp_test_3(id_1,?col_1,?col_2)?VALUES?(1,'a',null);
          INSERT?INTO?tmp_test_3(id_1,?col_1,?col_2)?VALUES?(2,'b','join_key_1');
          INSERT?INTO?tmp_test_3(id_1,?col_1,?col_2)?VALUES?(3,'c','join_key_2');


          INSERT?INTO?tmp_test_4(id_2,?col_3,?col_4)?VALUES?(1,'a',null);
          INSERT?INTO?tmp_test_4(id_2,?col_3,?col_4)?VALUES?(2,'b','join_key_1');
          INSERT?INTO?tmp_test_4(id_2,?col_3,?col_4)?VALUES?(3,'c','join_key_2');

          查看下tmp_test_3、tmp_test_4兩個案例表的數(shù)據(jù)(分布是類似的)

          現(xiàn)在有個業(yè)務(wù),部分數(shù)據(jù)存在tmp_test_3表,有一些存在tmp_test_4表,假設(shè)要得到兩個表中的數(shù)據(jù),需要這兩個表按col_2、col_4列JOIN連接。

          SELECT?
          ??*?
          FROM?
          ??tmp_test_3?t_a?
          Left?JOIN?
          ??tmp_test_4?t_b?
          on?
          ??t_a.col_2?=?t_b.col_4?;

          執(zhí)行一下上面的語句,會得到什么結(jié)果。

          結(jié)果顯示是col_2和col_4為空的數(shù)據(jù)是丟失了的。

          為什么?

          直接說原因:在tmp_test_3和tmp_test_4表中用于join的列存在NULL值,而NULL和任何值做比較都是返回的NULL(即不能對NULL進行!=、=、>、<等判斷,返回是NULL)。

          Coalesce真香函數(shù),將空值替換成一個默認值。

          SELECT?
          ??*?
          FROM?
          ??tmp_test_3?t_a?
          JOIN?
          ??tmp_test_4?t_b?
          on?
          ??COALESCE(t_a.col_2?,'aaa')=??COALESCE(t_b.col_4?,'aaa')??

          這樣就可以把tmp_test_3中包含NULL的數(shù)據(jù)記錄和tmp_test_4表中的NULL數(shù)據(jù)記錄JOIN起來。但是這里有個小問題是他會把這些NULL記錄全部匹配,所以實際應(yīng)用中可以按照業(yè)務(wù)需求來做取舍。

          2、聚合運算時遇到NULL值

          以下是教導(dǎo)主任的302班學(xué)生數(shù)學(xué)成績表,對應(yīng)了學(xué)生名字和成績。

          CREATE?TABLE?IF?NOT?EXISTS?tmp_score_baoqi_1
          (
          col_name?VARCHAR(255),
          col_core?int
          );

          INSERT?INTO?tmp_score_baoqi_1(col_name,?col_core)?VALUES?('a',null);
          INSERT?INTO?tmp_score_baoqi_1(col_name,?col_core)?VALUES?('b',86);
          INSERT?INTO?tmp_score_baoqi_1(col_name,?col_core)?VALUES?('c',78);
          INSERT?INTO?tmp_score_baoqi_1(col_name,?col_core)?VALUES?('d',65);??

          你驗證數(shù)據(jù)的時候發(fā)現(xiàn)有學(xué)生a的成績是空的(沒參加考試),心里美滋滋的預(yù)處理并且開始執(zhí)行如下腳本。

          SELECT
          ?avg(IFNULL(col_core,?0?)??)?
          FROM
          ?tmp_score_baoqi_1
          ??
          --?返回57.2500

          結(jié)果返回:這學(xué)期教導(dǎo)主任的302班學(xué)生數(shù)學(xué)平均成績是57.25分,四舍五入為58分,不及格。

          很好,執(zhí)行結(jié)果也出來了,也不報錯,但是教導(dǎo)主任卻生氣了,質(zhì)疑怎么可能他的班上學(xué)生數(shù)學(xué)成績不及格,需要你核查。

          經(jīng)過排查你發(fā)現(xiàn),原來你做預(yù)處理的時候把沒參加考試的學(xué)生a缺少的數(shù)學(xué)成績也算在內(nèi),用數(shù)值0代替NULL,嚴重影響了最終成績。

          這個小例子想說明的就是做聚合運算時要注意NULL值,一定要清楚count、sum、avg函數(shù)對NULL的處理:

          avg

          SELECT
          ?avg(col_core),avg(IFNULL(col_core,?0?)??)?
          FROM
          ?tmp_score_baoqi_1
          ??
          --?返回76.33、57.2500

          count

          SELECT
          ?count(1),count(*),count(col_core)
          FROM
          ?tmp_score_baoqi_1
          ??
          --?返回4、4、3

          sum:可以對單個列求和,也可以對多個列運算后求和忽略NULL值,且當(dāng)對多個列運算求和時,如果運算的列中任意一列的值為NULL,則忽略這行的記錄。

          補充一條,DISTINCT、ORDER BY、GROUP BY 遇到NULL值視為相等,較好理解,不做數(shù)據(jù)測試。

          請務(wù)必注意細節(jié),大概率能決定成敗,本節(jié)完。

          ·················END·················


          歡迎長按掃碼關(guān)注「數(shù)據(jù)管道」

          瀏覽 72
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲.www | 一区二区三区激情在线 | 人人摸人草 | 日韩无码小电影 | 爱爱图片一级 |