PowerBI之DAX神功:第1卷第4回 常見錯誤與處理方法
很多人DAX公式錯誤都是:咎由自??!因為他已經(jīng)習(xí)慣了Excel里亂七八糟的寫法,接下來我們就挨個的講一講,如果你是從正規(guī)數(shù)據(jù)庫上獲取的數(shù)據(jù),可能大多數(shù)問題你都遇不到。
一、文本與數(shù)值
根據(jù)《孫興華講PowerBI火力全開》筆記第1集 運(yùn)算符
數(shù)值加數(shù)值 = [數(shù)值]+[數(shù)值]? ? ? // 520 + 1314 = 1834
文本加數(shù)值 = [字符]+[數(shù)值]? ? ? // "520" + 1314 = 1834
文本加文本 = [字符]+[字符]? ? ? // "520" + "1314" = 1834
數(shù)值連接數(shù)值 = [數(shù)值] & [數(shù)值]? ?// 520 & 1314 = "5201314"
文本連接數(shù)值 = [字符] & [數(shù)值]? ?// "520" & 1314 = "5201314"
文本連接文本 =? [字符] & [字符]? // "520" & "1314" = "5201314"
你會發(fā)現(xiàn)規(guī)律:
使用“+”時,他會將字符自動轉(zhuǎn)化成數(shù)值進(jìn)行計算
使用“&”時,他會將數(shù)值自動轉(zhuǎn)化成文本進(jìn)行計算
你真的認(rèn)為它永遠(yuǎn)都能轉(zhuǎn)換嗎?例如:"1"不等于1,"520"大于1314
因為:"1"=49? ? 而 :1 = 1
因為:"520"=53? 而:1314=1314
因為ASCII碼?不!你這是,Excel邏輯,在PowerBI的DAX中,文本與數(shù)值就無法進(jìn)行比較運(yùn)算。DAX會報錯,會提示你:
DAX比較操作不支持將類型為Text的值和類型為Integer的值進(jìn)行比較,請考慮使用Value或Format函數(shù)轉(zhuǎn)換其中一個值。
可以使用《孫興華講PowerBI火力全開》筆記第17課轉(zhuǎn)換函數(shù) <11>VALUE【將文本轉(zhuǎn)數(shù)值】

所以建議大家無論何時何地,都不要讓DAX自已轉(zhuǎn)換數(shù)據(jù)類型,你要檢查每個字段的數(shù)據(jù)類型是否正確,如果你的表導(dǎo)入時,這一列都是數(shù)值,那PowerBI會自動識別為數(shù)值,就是因為大多數(shù)人我形我素(如圖1-4-1)。造成后期麻煩不斷。
規(guī)避方法:誰在這樣輸入數(shù)據(jù),我們就讓他來分析:)

剛才我們遇到的“520”或者“1”都是文本型的數(shù)字,但是遇到(圖1-4-1)這種情況你怎么辦呢?這就引出了我們第二個概念:
二、如何正確的規(guī)避錯誤
如圖1-4-2,因為銷售數(shù)量是文本型,單價是數(shù)值型,我們直接【新建列】計算,會報錯!

《孫興華講PowerBI火力全開》筆記第12課.<1>IFERROR 遇到錯誤時使用指定數(shù)值替換
如圖1-4-3,我們可以使用IFERROR函數(shù)判斷發(fā)生錯誤時,返回空。這也是推薦的方法!

圖1-4-4,也可以使用同樣的函數(shù),將錯誤返回成指定數(shù)值。

圖1-4-5,但是,不能將錯誤轉(zhuǎn)化成文本。

為什么不能將錯誤寫成中文或英文?
因為銷售金額這一列在計算過程中,數(shù)據(jù)類型已經(jīng)變成了數(shù)值
而當(dāng)初導(dǎo)入Excel文件時,銷售數(shù)量這列是文本型,你看都靠左,而單價這列是數(shù)值型都靠右
因為銷售數(shù)量那一列有一個孫興華,所以就自動使用了文本型(即可以存數(shù)值又可以存文本)
如果你想強(qiáng)行轉(zhuǎn)換結(jié)果的類型,也沒有問題,但是這屬于胡鬧,用辦公軟件的人有兩個最嚴(yán)重的胡鬧
1. 非打印表格使用合并單元格或多表頭,胡鬧指數(shù)100%
2. 數(shù)據(jù)類型混亂,同一字段各種類型胡寫,胡鬧指數(shù)100%
三、為何推薦將錯誤、空值、缺失值轉(zhuǎn)化為BLANK()
在DAX中,通常缺失值,空值都使用BLANK()處理
科普:
缺失值包含空值(null)、0、False等
null值是空值,是缺失值的一種
你心里應(yīng)該非常清楚,如果(圖1-4-5)的結(jié)果對錯誤的返回值寫了中文或英文,再次計算時仍然要規(guī)避下一個錯誤,那為何你還要這樣做呢?
強(qiáng)行寫也不是不可以,但是無意義,還添亂:如圖1-4-6
《孫興華講PowerBI火力全開》筆記第17課.轉(zhuǎn)換函數(shù) <07>CONVERT函數(shù)【轉(zhuǎn)換為指定數(shù)據(jù)類型】
銷售金額 = IFERROR(CONVERT([銷售數(shù)量]*[單價],STRING),"這是錯的")

現(xiàn)在如你所愿”銷售金額“這一列變成了文本型
你現(xiàn)在寫一個度量值,并將它放到矩陣中,會有什么結(jié)果?如圖1-4-7
總金額 = sum(Sheet1[銷售金額])

原理:IFERROR之所以遇到錯誤時使用指定數(shù)值替換,因為你在計算,計算結(jié)果本身就是數(shù)值,所以必需用數(shù)值,這是數(shù)據(jù)類型的統(tǒng)一性。
你說了一個謊就要去用另一個謊去圓
IFERROR(表達(dá)式,BLANK()或數(shù)值)
有些人會抬扛:如果我的表達(dá)式是&連接兩個列,報錯以后,是不是可以返回文本?可以!但是,如果你原始的兩個列本身不是錯誤,你怎么可能連接出錯誤?
那么問題來了,為何推薦將錯誤轉(zhuǎn)化為BLANK()?答:為了不再出錯!

銷售金額 = IFERROR(CONVERT([銷售數(shù)量]*[單價],STRING),"錯了")
銷售金額2 = IFERROR([銷售數(shù)量]*[單價],BLANK())
銷售金額*10 = [銷售金額]*10
銷售金額2*10 = [銷售金額2]*10
我們再進(jìn)行一個測試:

銷售數(shù)量2 = if([銷售數(shù)量]="孫興華",BLANK(),[銷售數(shù)量])
空字符串 = [銷售數(shù)量2]=""
銷售金額 = IFERROR([銷售數(shù)量]*[單價],BLANK())
0 = [銷售金額]=0?
如果這一列,是文本類型,那么,BLANK()就是空字符串
如果這一列,是數(shù)值類型,那么,BLANK()就是0
這個時候,數(shù)學(xué)邏輯好的人,就會舉一反三,那么日期/時間型呢?因為他們本身也是數(shù)字類型的演化,所以同理數(shù)字。
但是要注意:并不是任何類型與BLANK()進(jìn)行四則運(yùn)算結(jié)果都是BLANK()
例如:
1+BLANK()=BLANK()
BLANK()+BLANK()=BLANK()
這只限定于加減乘除
PS: 水軍經(jīng)常會拿常識說我講的內(nèi)容不適合小白,例如他聽不懂"唯一值"是什么?如果哪位水軍聽不懂四則運(yùn)算是什么,只能證明你的小學(xué)畢業(yè)證是假的。
另外需要注意的是:日期類型的BLANK()+1? 不等于BLANK()
修證:在視頻上我講這里時忽略了日期類型,大家要特別注意
但是:連接和比較運(yùn)算就不一樣了,你需要舉一反三:
"孫興華" & BLANK() = "孫興華"? ? //因為這個時候, BLANK()代表空字符串
520? & BLANK() = "520"? ? ??//因為&的結(jié)果都是字符串,所以BLANK()代表空字符串
"孫興華" >? BLANK()? ? ? ? ? ? //返回: True? 因為這個時候, BLANK()代表空字符串
"" = BLANK()? ? ? ? ? ? ? ? ? ? ? ?//返回: True? 因為這個時候, BLANK()代表空字符串
1 >? BLANK()? = True? ? ? ? ?//返回: True? 因為這個時候, BLANK()代表0
0= BLANK()? ? ? ? ? ? ? ? ? ? ? ?//返回: True? 因為這個時候, BLANK()代表0
如果是邏輯判斷呢?廢話連篇!True和False是0和1
那你說: True &&? BLANK()? ?是什么?? ? //? 1 and 0? ?那不還是0嗎???
我小時候打撲克牌,有一種玩法,就是誰拿到大王小王(等同于BLANK()),可以用它們代替任何牌,可能地區(qū)不同我們的玩法不同,我們「塞伯坦星球」就是這么玩的。

例如,我手上有? 3、4、6、7、9、10、J、Q、K、A
很明顯,我若將手上順子的9、10、J、Q、K、A出掉,手上的3、4、6、7就變成了單牌。
如果大小王在手,我可以這樣出
3、4、大王、6、7、小王、9、10、J、Q、K、A? ? ? ? ?
//大王代替5,小王代替8
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 或
3、4、小王、6、7、大王、9、10、J、Q、K、A? ? ? ??
//小王代替5,大王代替8
四、IF與IFERROR的區(qū)別
大家都知道,分母為0時會報錯,除非你用安全除法
=IFERROR(5/0,BLANK())? ??
等同于
= If(ISERROR(5/0),BLANK(),5/0)??
《孫興華講PowerBI火力全開》筆記第12課? <02> if條件判斷
《孫興華講PowerBI火力全開》筆記第22課? <03> 信息函數(shù)中的ISERROR
=ISERROR(5/0)? ? ? //返回:True ,功能判斷5/0是不是一個錯誤
很明顯,我們使用IFERROR更簡單,但是現(xiàn)在的情況是:
如果5/0是個錯誤,我們就返回BLANK(),否則返回5/0的結(jié)果
現(xiàn)在我們換一道題,如果 '表'[列名] 是BLANK(),就怎么樣,否則怎么樣?
我們有IFERROR,但是沒見過IFBLANK,然而我們有ISBLANK
《孫興華講PowerBI火力全開》筆記第22課?<03>信息函數(shù)中? 還有很多判斷函數(shù)可供使用


你知道"銷售金額3"為什么報錯嗎?
因為:[銷售數(shù)量2]*[單價] 返回數(shù)值型,而“哈哈它是空的”是個文本型
五、拋開速度,IFERROR與ISERROR最大的弊端

商1 =iferror([分子]/[分母],Blank())
商2=if(iserror([分子]/[分母]),Blank(),[分子]/[分母])
商3=if([分母]<>0,[分子]/[分母],Blank())
商4=if([分母]<>0,[分子]/[分母],ERROR("分母不能為0"))
商1和商2需要先判斷[分子]/[分母]是不是一個錯誤,理論上比商3慢,是因為多了一步判斷。
但是,實際你不易感覺出來,就好比有些奇怪的人們對比照片和視頻清晰度一樣。
例如照片:它們將照片放大放大再放大,對比銳度,焦外,二線性。
例如視頻:他們將畫面定住,然后趴在電視機(jī)前,看看演員的毛孔。
另一個問題才是最致命的,官方語言說:截獲內(nèi)層級別計算時發(fā)生的錯誤

商1 = CALCULATE(sumx('Sheet2',iferror([分子]/[分母],Blank())))
商2 = iferror(sumx('Sheet2',[分子]/[分母]),Blank())

IFERROR與ISERROR同理,官方語言也是很好理解,可即便是萌新小白
你也應(yīng)該清楚,他的運(yùn)算規(guī)則,是從內(nèi)到外,你搞清楚運(yùn)算規(guī)則,原理不攻而破。
六、ERROR函數(shù)測試未通過
首先聲明,我并不是要黑誰和批判誰,這只是我在使用中發(fā)現(xiàn)的問題,和大家分享一下,大家可以自行測試,有問題可以提,互通有無。
圖1-4-13 是某位DAX原理講師,在知乎上引用《The Definitive Guide to DAX》原著中的內(nèi)容:

第1個 = IFERROR (?
SQRT ( Test[Temperature] ),
0
)
這個度量值肯定是沒問題的,但是第2個度量值就有問題了:

第2個 = IF (
Test[Temperature] >= 0,?
SQRT ( Test[Temperature] ),
ERROR ( "The temperature cannot be a negative number. Calculation aborted." )
)

處理方法:

錯誤提示 = IFERROR(CONVERT(SQRT(Test[Temperature]),STRING),"The temperature cannot be a negative number. Calculation aborted.")
七、PowerBI中的DAX使用變量時不受版本影響
Marco Russo和Alberto Ferrari 兩位意大利專家寫的《The Definitive Guide to DAX》曾指出,使用變量時,會根據(jù)產(chǎn)品DAX版本不同,返回不同的結(jié)果
親測:2021年6月版的PowerBI不受影響

但是在PowerPivot中,可能就真的不一樣了。PowerPivot內(nèi)置在Excel中,Excel2016、2019、2021、365版本眾多,365訂閱尚且更新,其它版本…
2021年6月版的PowerBI中:以下三種寫法,均正常返回結(jié)果
測試1=iferror(5/0,520)
// 先定義變量,輸出時再做判斷
測試2 =?
var abc= 5/0
return
? ? iferror(abc,520)
//先判斷,再輸出?
測試3 =?
iferror(?
? ? var abc=5/0
? ? return
? ? ? ? abc,
? ? 520
)
八、防抬扛:分母為零時計算報錯可用安全除法
《孫興華講PowerBI火力全開》筆記第13課 <01> 安全除法
語法:DIVIDE(分子,分母,[替換結(jié)果])
替換結(jié)果可以省略不寫,省略時返回為空。
除法 = [分子]/[分母]

