第1章 什么是DAX?
1.1 理解數(shù)據(jù)模型
1.2 DAX FOR EXCEL用戶
1.3 DAX for SQL開發(fā)人員
1.4 DAX for MDX開發(fā)人員
1.5 DAX FOR POWER BI 用戶
DAX for SQL開發(fā)人員
如果您習(xí)慣使用SQL語(yǔ)言,那么您已經(jīng)使用了許多表并在列之間創(chuàng)建了聯(lián)接以設(shè)置關(guān)系。從這個(gè)角度來(lái)看,您可能會(huì)在DAX世界中感到賓至如歸。實(shí)際上,在DAX中進(jìn)行計(jì)算只是查詢一組由關(guān)系連接在一起的表并匯總值。
關(guān)系處理
SQL和DAX之間的第一個(gè)區(qū)別是關(guān)系在模型中的工作方式。在SQL中,我們可以在表之間設(shè)置外鍵來(lái)聲明關(guān)系,但是除非明確說(shuō)明,否則引擎永遠(yuǎn)不會(huì)在查詢中使用這些外鍵。例如,如果我們有一個(gè)Customers表和Sales表,其中CustomerKey是Customers表的主鍵的Sales表的外鍵,我們可以寫出下面的查詢:
SELECT
Customers.CustomerName,
SUM ( Sales.SalesAmount ) AS SumOfSales
FROM
Sales
INNER JOIN Customers
ON Sales.CustomerKey =
Customers.CustomerKey
GROUP BY
Customers.CustomerName
盡管我們?cè)谀P椭惺褂猛怄I聲明了關(guān)系,但仍然需要在查詢條件中明確聲明連接狀態(tài)。盡管這種方法使查詢更加冗長(zhǎng),但是它很有用,因?yàn)槟梢栽诓煌牟樵冎惺褂貌煌穆?lián)接條件,從而在表達(dá)查詢的方式上具有很大的自由度。
在DAX中,關(guān)系是模型的一部分,并且它們都是LEFT OUTER JOINs。在模型中定義它們時(shí),您不再需要在查詢中指定聯(lián)接類型:每當(dāng)您使用與主表相關(guān)的列時(shí),DAX都會(huì)在查詢中自動(dòng)使用LEFT OUTER JOIN。因此,在DAX中,您將按以下方式編寫先前的SQL查詢:
EVALUATE
SUMMARIZECOLUMNS (
Customers[CustomerName],
"SumOfSales", SUM ( Sales[SalesAmount] )
)
因?yàn)镈AX知道Sales和Customer之間的現(xiàn)有關(guān)系,所以它會(huì)按照模型自動(dòng)進(jìn)行聯(lián)接。最后,SUMMARIZECOLUMNS函數(shù)需要按Customers [CustomerName]進(jìn)行分組,但是我們沒(méi)有關(guān)鍵字:SUMMARIZECOLUMNS自動(dòng)按選定的列對(duì)數(shù)據(jù)進(jìn)行分組。
DAX是一種功能語(yǔ)言
SQL是一種聲明性語(yǔ)言。您可以通過(guò)聲明要使用SELECT檢索的數(shù)據(jù)集來(lái)定義所需的內(nèi)容語(yǔ)句,而不必?fù)?dān)心引擎實(shí)際上如何檢索信息。
另一方面,DAX是一種功能語(yǔ)言。在DAX中,每個(gè)表達(dá)式都是一個(gè)函數(shù)調(diào)用。函數(shù)參數(shù)又可以是其他函數(shù)調(diào)用。參數(shù)的評(píng)估可能會(huì)導(dǎo)致DAX執(zhí)行復(fù)雜的查詢以計(jì)算結(jié)果。
例如,如果我們只想檢索居住在歐洲的客戶,則可以使用SQL編寫此查詢:
SELECT
Customers.CustomerName,
SUM ( Sales.SalesAmount ) AS SumOfSales
FROM
Sales
INNER JOIN Customers
ON Sales.CustomerKey =
Customers.CustomerKey
WHERE
Customers.Continent = 'Europe'
GROUP BY
Customers.CustomerName
使用DAX,我們不會(huì)在查詢中聲明WHERE條件。相反,我們使用特定的函數(shù)(FILTER)來(lái)過(guò)濾結(jié)果:
您會(huì)看到FILTER是一個(gè)函數(shù):它僅返回居住在歐洲的客戶,從而產(chǎn)生預(yù)期的結(jié)果。我們嵌套函數(shù)的順序和所使用函數(shù)的種類對(duì)結(jié)果和引擎的性能都有很大的影響。這也發(fā)生在SQL中,盡管在SQL中我們相信查詢優(yōu)化器會(huì)找到最佳查詢方案。在DAX中,盡管查詢優(yōu)化器做得很好,但作為程序員,您在編寫優(yōu)質(zhì)代碼方面承擔(dān)了更多責(zé)任。
DAX作為一種編程和查詢語(yǔ)言
在SQL中,查詢語(yǔ)言和編程語(yǔ)言(即用于在數(shù)據(jù)庫(kù)中創(chuàng)建存儲(chǔ)過(guò)程、視圖和其他代碼段的指令集)之間存在明顯的區(qū)別。每個(gè)SQL語(yǔ)言都有其自己的語(yǔ)句,可讓程序員使用代碼豐富數(shù)據(jù)模型。但是,DAX實(shí)際上在查詢和編程之間沒(méi)有區(qū)別。豐富的函數(shù)集可以操縱表,并可以依次返回表。上一個(gè)查詢中的FILTER函數(shù)就是一個(gè)很好的例子。
在這方面,似乎DAX比SQL更簡(jiǎn)單。當(dāng)您將它作為一種編程語(yǔ)言(最初使用)學(xué)習(xí)時(shí),您將知道將其也用作查詢語(yǔ)言所需的一切。
DAX和SQL中的子查詢和條件
作為查詢語(yǔ)言,SQL最強(qiáng)大的功能之一就是可以使用子查詢。DAX具有類似的概念。但是,對(duì)于DAX子查詢,它們?cè)醋哉Z(yǔ)言的功能性質(zhì)。
例如,要檢索專門針對(duì)購(gòu)買了價(jià)值超過(guò)100美元的客戶的客戶和總銷售額,我們可以在SQL中編寫以下查詢:
SELECT
CustomerName,
SumOfSales
FROM (
SELECT
Customers.CustomerName,
SUM ( Sales.SalesAmount ) AS SumOfSales
FROM
Sales
INNER JOIN Customers
ON Sales.CustomerKey =
Customers.CustomerKey
GROUP BY
Customers.CustomerName
) AS SubQuery
WHERE
SubQuery.SumOfSales > 100
通過(guò)嵌套函數(shù)調(diào)用,我們可以在DAX中獲得相同的結(jié)果:
EVALUATE
FILTER (
SUMMARIZECOLUMNS (
Customers[CustomerName],
"SumOfSales", SUM ( Sales[SalesAmount]
)
),
[SumOfSales] > 100
)
在此代碼中,先檢索CustomerName和SumOfSales的子查詢?cè)佥斎氲?em>FILTER函數(shù)中,FILTER函數(shù)僅保留SumOfSales大于100 的行?,F(xiàn)在,此代碼對(duì)您來(lái)說(shuō)似乎不可讀。但是,一旦您開始學(xué)習(xí)DAX,就會(huì)發(fā)現(xiàn)使用子查詢比在SQL中容易得多,并且由于DAX是一種功能性語(yǔ)言,它自然會(huì)流行。