Upcoming SlideShare
×

# Sessão Especial: PowerPivot com Alberto Ferrari

2,044 views

Published on

Apresentação do Alberto Ferrari sobre PowerPivot: Many-to-Many in DAX numa Sessão especial da Comunidade NetPonto.

6 Likes
Statistics
Notes
• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

Views
Total views
2,044
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
0
0
Likes
6
Embeds 0
No embeds

No notes for slide
• Briefly introduce what a filtercontextis
• Introduce the concept of filtercontext, explaining in high detailthat the contextisdetermined by the filter, the rows, the columns and the slicer.Provideexamples with the aid of the figures.
• Brieflyexplainwhat a rowcontextis, similar to «currentrow»
• Explain in greatdetailwhathappens to the variouspieces of thefiltercontextduringThe evaluation of thiscell.Filtercontextcovers the white area.FILTER isevaluated in the filtercontext and introduces a new rowcontext.Inside thatrowcontext the conditionisevaluatedSinceitis false for onerow, FILTER doesnotreturnit.Thisisnotreally the addition of a condition to a filter, evenif the finalresultis the same.Don’tbothertoomuch with the theoryanyway, wewillhave a lot of time to discuss more detailsLater on therewill be time to discussit.
• Explain in highdetailwhathappens with the ALL function, whichsimplyignores the currentevaluationcontexts.
• Example of a formula whichmixestwodifferentfilteroperations.
• This slide isuseful to chek the error, itmight be useful to take a look at a demo, ifthereis time enough.
• Follow the slide animation and show how the filtercontextinteracts with the variousitems.
• Follow the slide animation and show how the filtercontextinteracts with the variousitems.
• Use the slide to show the effect of CALCULATE whichopens a new filtercontextbutreplaceonly part of the wholefilter.
• ### Sessão Especial: PowerPivot com Alberto Ferrari

1. 1. http://netponto.org Sessão Especial:PowerPivot com Alberto Ferrari =DATE(2012, 02, 13) Twitter hashtag: #netponto
3. 3. Também disponível em vídeo... Assista!http://www.youtube.com/watch?v=TXLJTJ8ycuw
4. 4. www.sqlbi.coma brand of
5. 5. Alberto FerrariSenior ConsultantSQLBI.COMalberto.ferrari@sqlbi.com Many-to-many Relationship in DAX When Many To Many Are Really Too Many
6. 6. Who We Are• BI Experts and Consultants• Founders of www.sqlbi.com o Problem Solving o Complex Project Assistance o DataWarehouse Assesments and Development o Courses, Trainings and Workshops• Book Writers• Microsoft Business Intelligence Partners• SSAS Maestros – MVP – MCP
7. 7. Agenda• Brief recall of basic DAX concepts• Many To Many Relationships o Data Model o DAX Formula pattern• Classical Many To Many• Cascading Many To Many• Survey Data Model• Basket Analysis
8. 8. The Many-To-Many Revolution 2.0• BISM Multidimensional• BISM Tabular• Many more models than in the session• Available on www.sqlbi.com 8
9. 9. A very brief recall of basic DAX conceptsDAX Basics
10. 10. What is DAX?• Programming language of Vertipaq o PowerPivot o BISM Tabular• Resembles Excel• Important differences o No concept of «row» and «column» o Different type system• Many new functions• Designed for querying tabular models
11. 11. Evaluation Contexts• Contexts under which a formula is evaluated• Filter Context o Set of «active rows» for the computation o Defined by rows, columns, filters, slicers o One for each cell of a PivotTable• Row Context o Current row during iterations o Contains a single row o Defined by formulas, not pivot tables
12. 12. Filter Context• Defined by o Row Selection o Column Selection o Report Filters o Slicers Selection• Rows outside of the filter context o Are not considered for the computation• Defined automatically by PivotTable
13. 13. Example of a Filter Context
14. 14. Row Context• Defined by o Calculated column definition • Defined Automatically for each row o Row Iteration functions • SUMX, AVERAGEX … • All «X» functions • Defined by the user formulas• Needed to evaluate column values
15. 15. Adding Filters – Single Table SUMX( FILTER( Orders, Orders[Price] > 1 ), Orders[Amount] )
16. 16. Removing Filters – Single Table SUMX( ALL (Orders) Orders[Amount] )
17. 17. Mixing Filters – Single Table SUMX( FILTER( ALL( Orders ), Orders[Channel]="Internet" ), Orders[Amount] )
18. 18. Filters and Relationships OrderDetail OrderHeader Products PK,FK1 OrderCodePK OrderCode PK ProductCode PK OrderLineNumber OrderDate Product Amount TotalAmount FK1 ProductCategoryCode FK2 ProductCode ProductCategory PK ProductCategoryCode tCategoryCode
19. 19. Row Context – Many Tables• Row Context o Does not propagate over relationships
20. 20. Filter Context – Many Tables
21. 21. Filter Context – Many Tables
22. 22. CALCULATE SyntaxThe most • Powerful function • Complex to understandSyntax is very simpleCALCULATE ( Expression, Filter1, … Repeated many times, as needed Filtern)
23. 23. CALCULATE Tasks• Partially replaces the filter context• Conditions o Can replace a whole table o Can replace a single column• Transforms a row context into a filter context
24. 24. CALCULATE – Single Table CALCULATE ( SUMX ( Orders, Orders[Amount] ) ALL (Orders[Channel]) )
25. 25. CALCULATE and ContextsLet us look at CALCULATE and your understanding of contexts…Using a simple exercise SUM ( FactInternetSales[SalesAmount] )
27. 27. Current Accounts Model M2M Dim_Date PK ID_Date Date Many to Many Account – Customer Fact_Transaction Bridge_AccountCustomer Dim_Account PK ID_Transaction PK,FK1 ID_Account PK ID_Account FK1 ID_Account PK,FK2 ID_Customer FK3 ID_Type Account FK2 ID_Date Amount Dim_Type Dim_Customer PK ID_Type PK ID_Customer Type CustomerName
28. 28. No support for M2M in Tabular• Multidimensional handles M2M o Directly in the engine o Performance may suffer• Tabular does not handle M2M o Only plain vanilla 1:N relationships o Only on one column o Seems not to be enough…• But… hey, we have DAX!
29. 29. Demo – Classical M2M• We will start looking at the final result• Then, we dive into the DAX code
30. 30. The M2M DAX Pattern• Leverages o CALCULATE o Row Contexts o Filter Contexts o Automatic transformation of Row Context into Filter Context using CALCULATE• Next slide: the formula. o Keep it in mind o It will appear quite often from now on
31. 31. The DAX FormulaThe pattern of many-to-many is always the same AmountM2M := CALCULATE ( SUM (Fact_Transaction[Amount]), FILTER ( Dim_Account, CALCULATE ( COUNTROWS (Bridge_AccountCustomer) ) > 0 ) )
32. 32. What the formula should perform Fact_Transaction Dim_Account PK ID_Transaction FK1 ID_Account PK ID_Account Filter on Dim_Account FK3 ID_Type Account FK2 ID_Date Amount Bridge_AccountCustomer PK,FK1 ID_Account PK,FK2 ID_Customer Dim_Customer PK ID_CustomerAmountM2M := Filter on Dim_Customer CustomerNameCALCULATE ( SUM (Fact_Transaction[Amount]), FILTER ( Dim_Account, CALCULATE ( COUNTROWS (Bridge_AccountCustomer) ) > 0 ))
33. 33. How the formula works Fact_Transaction Dim_Account PK ID_Transaction PK ID_Account FK1 ID_Account FK3 ID_Type Account FK2 ID_Date Amount Bridge_AccountCustomer PK,FK1 ID_Account PK,FK2 ID_Customer Dim_Customer PK ID_CustomerAmountM2M := CustomerName The filter is applied by the Tabular data modelCALCULATE ( SUM (Fact_Transaction[Amount]), FILTER ( Dim_Account, CALCULATE ( COUNTROWS (Bridge_AccountCustomer) ) > 0 ))
34. 34. How the formula works Fact_Transaction Dim_Account FILTER: For each row in Dim_Account PK ID_Transaction PK ID_Account CALCULATE: filters the bridge FK1 ID_Account FK3 ID_Type Account FK2 ID_Date Amount Bridge_AccountCustomer PK,FK1 ID_Account PK,FK2 ID_Customer Dim_Customer PK ID_CustomerAmountM2M := CustomerName The filter is applied by the Tabular data modelCALCULATE ( SUM (Fact_Transaction[Amount]), FILTER ( Dim_Account, CALCULATE ( COUNTROWS (Bridge_AccountCustomer) ) > 0 ))
35. 35. How the formula works Fact_Transaction Dim_Account FILTER: For each row in Dim_Account PK ID_Transaction PK ID_Account CALCULATE: filters the bridge FK1 ID_Account FK3 ID_Type Account FK2 ID_Date Amount Bridge_AccountCustomer PK,FK1 ID_Account Only rows in Dim_Account where PK,FK2 ID_Customer COUNTROWS () > 0 survive the FILTER Dim_Customer PK ID_CustomerAmountM2M := CustomerName The filter is applied by the Tabular data modelCALCULATE ( SUM (Fact_Transaction[Amount]), FILTER ( Dim_Account, CALCULATE ( COUNTROWS (Bridge_AccountCustomer) ) > 0 ))
36. 36. How the formula works Fact_Transaction Dim_Account FILTER: For each row in Dim_Account PK ID_Transaction PK ID_Account CALCULATE: filters the bridge FK1 ID_Account FK3 ID_Type Account FK2 ID_Date Amount Bridge_AccountCustomer PK,FK1 ID_Account Only rows in Dim_Account where PK,FK2 ID_Customer COUNTROWS () > 0 survive the FILTER Dim_Customer PK ID_CustomerAmountM2M := CustomerName This filter is applied by the Tabular data modelCALCULATE ( SUM (Fact_Transaction[Amount]), FILTER ( Dim_Account, SUM is evaluated only for the CALCULATE ( COUNTROWS (Bridge_AccountCustomer) accounts filtered from the ) > 0 customers ))
37. 37. The Karma of CALCULATEAmountM2M_Correct := CALCULATE ( AmountM2M_Wrong := CALCULATE ( SUM (Fact_Transaction[Amount]), SUM (Fact_Transaction[Amount]), FILTER ( FILTER ( Dim_Account, Dim_Account, CALCULATE ( COUNTROWS (Bridge_AccountCustomer) COUNTROWS (Bridge_AccountCustomer) > 0 ) > 0 ) ) )) BI123|many-to-many In DAX 37
38. 38. Wrong formula in action Customer Customer Account Account Mark Mark Mark Mark Paul Paul Paul Paul Robert Robert Robert Robert Luke Luke Luke Luke Mark Mark-Robert Mark-Robert Robert Mark-Robert Mark-Paul Mark Mark-Paul Paul Mark-PaulAmountM2M :=CALCULATE ( All the rows in the SUM (Fact_Transaction[Amount]), FILTER ( Dim_Account, Account table ) COUNTROWS (Bridge_AccountCustomer) > 0 survived the FILTER)
39. 39. Many-to-many in action Customer Customer Account Account Mark Mark Mark Mark Paul Paul Paul Paul Robert Robert Robert Robert Luke Luke Luke Luke Mark Mark-Robert Mark-Robert Robert Mark-Robert Mark-Paul Mark Mark-Paul Paul Mark-PaulAmountM2M :=CALCULATE ( SUM (Fact_Transaction[Amount]), FILTER ( Dim_Account, Two rows in the CALCULATE ( COUNTROWS (Bridge_AccountCustomer) Account table ) > 0) ) survived the FILTER
40. 40. The Karma of CALCULATEAmountM2M_Correct := CALCULATE ( AmountM2M_Wrong := CALCULATE ( SUM (Fact_Transaction[Amount]), SUM (Fact_Transaction[Amount]), FILTER ( FILTER ( Dim_Account, Dim_Account, CALCULATE ( COUNTROWS (Bridge_AccountCustomer) COUNTROWS (Bridge_AccountCustomer) > 0 ) > 0 ) ) )) BI123|many-to-many In DAX 40
41. 41. Many to Many - Conclusions• Complexity o Not in the data model o Only in the formula• Need to understand o CALCULATE o Relationships in TabularThis is just the beginning of our journey 
42. 42. Cascading Many To Many
43. 43. Cascading Many To Many Filter on Dim_Account The pattern is the same, but this time we need to jump two steps to complete our task Filter on Dim_Category
45. 45. Cascading Many To Many CALCULATE ( CALCULATE ( SUM (Fact_Transaction[Amount]), FILTER ( Dim_Account, CALCULATE ( COUNTROWS (Bridge_AccountCustomer) ) > 0 ) ), FILTER ( Dim_Customer, CALCULATE ( COUNTROWS (Bridge_CustomerCategory) ) > 0 ) )
46. 46. Cascading Many To Many• Generic Formula• Works with any number of steps• Be careful o Start with the farthest table o Move one step a time towards the fact table o One CALCULATE for each step• Complexity: M x N (geometric…)
47. 47. Cascading Alternative Dim_Date Cascading many to many flattened Fact_Transaction PK ID_Date Dim_Account PK ID_Transaction Date PK ID_Account FK1 ID_Account FK3 ID_Type Account FK2 ID_Date Amount Bridge_AccountCustomerCategory Dim_Type Need for some PK ID_Type FK1 FK3 ID_Account ID_Customer ETL here FK2 ID_Category Type Dim_Category Dim_Customer PK ID_Category PK ID_Customer CategoryName CustomerName
48. 48. Cascading Alternative Dim_Date Cascading many to many flattened Fact_Transaction PK ID_Date Dim_Account PK ID_Transaction Date PK ID_Account FK1 ID_Account FK3 ID_Type Account FK2 ID_Date Amount Bridge_AccountCustomerCategory Dim_Type FK1 ID_Account PK ID_Type FK3 ID_Customer FK2 ID_Category Type Dim_Category The bridge now «feels» Dim_Customer PK ID_Category three different filters, but PK ID_Customer CategoryName the formula becomes a CustomerName classical many to many and runs faster
49. 49. Flattened Cascading Many To Many• Flattened Data Model• Faster than the cascading one• Simpler formula• Needs ETL• Worth a try in Multidimensional too…
50. 50. Survey
51. 51. Survey Data Model• One customer answers many questions• One question is answered by many customers• We want to use a PivotTable to query this
52. 52. Survey Scenario «What is the yearly income of consultants?»• In other words: o Take the customers who answered «Consultant» at the «Job» question o Slice them using the answer to the question «Yearly Income»
53. 53. Survey - Demo
54. 54. Survey Analytical Data Model Filter1 Question1 = «Job» PK ID_Answer Answer1 = «Consultant» Question Answer Customers AnswersPK ID_Customer Customer FK1,FK2 ID_Answer Category FK3 ID_Customer Filter2 PK ID_Answer Question Answer Question2 = «Yearly Income» • Two «Filter» Dimensions o One for «Job» = «Consultants» o One for «Yearly Income»
55. 55. Survey: The Final Result• Value = Customer Count• The fact table, this time, acts as the bridge
56. 56. Survey Analytical Data Model Filter1 PK ID_Answer Question Answer Customers Answers PK ID_Customer Customer FK1,FK2 ID_Answer Category FK3 ID_Customer Filter2 PK ID_Answer Question AnswerNo relationship between the facttable and the two filter dimensionsBecause here is only one value for ID_Answer
57. 57. Survey Analytical Data Model Filter1 PK ID_Answer Question Answer Customers Answers PK ID_Customer Customer FK1,FK2 ID_Answer Category FK3 ID_Customer Filter2 PK ID_Answer Question Answer• The two filters• Are applied on the Customers table• Use separate instances of the Answers table
60. 60. Survey - Conclusions• Very powerful data model• Very compact o Duplicates only dimensions o Different from the same pattern in Multidimensional• Handles any number of questions o We have shown two o But it is not a limit• Interesting topics o Fact table as the bridge o Relationships set in DAX o Can be queried with a simple PivotTable
62. 62. Basket Analysis: The Scenario Of all the customers who have bought a Mountain Bike, how many have never bought a mountain tire tube?
63. 63. Basket Analysis in SQLTwo iterations over the fact table needed SELECT COUNT (DISTINCT A.CustomerID) FROM FactSales A INNER JOIN FactSales B ON A.CustomerID = B.CustomerID WHERE A.ProductModel = ‘MOUNTAIN TIRE TUBE AND A.Year <= 2004 AND B.ProductModel = ‘MOUNTAIN-100 AND B.Year <= 2004
64. 64. Look the query plan… This is the fact table… Do you really like to self-join it?
65. 65. Basket Analysis: The Data Model Of all the customers who have bought a Mountain Bike, how many have never bought a mountain tire tube?We can filter «Mountain Tire Tube» withthis table but… where do we filter«Mountain Bike»?
66. 66. Basket Analysis: The Data Model 2° filter: «Mountain Bike» No relationships1° filter: «Mountain Tire Tube»
68. 68. The Final Result 2° filter: «Mountain Tire Tube» HavingProduct = Bought Both NotHavingProduct = Bought Bike, No Tire1° filter: «Mountain Bike»
69. 69. HavingProductsLet us start with HavingProducts, it is easier HavingProduct := CALCULATE ( COUNTROWS (DISTINCT (FactSales[CustomerKey])), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ), FILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0 ))
70. 70. HavingProductsCount the number of customers…HavingProduct := CALCULATE ( COUNTROWS (DISTINCT (FactSales[CustomerKey])), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ), FILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0 ))
71. 71. HavingProductsIn the period of time before the end of the currentlyselected filter…HavingProduct := CALCULATE ( COUNTROWS (DISTINCT (FactSales[CustomerKey])), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ), FILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0 ))
72. 72. HavingProductsThis filter needs a bit of attention… HavingProduct := CALCULATE ( COUNTROWS (DISTINCT (FactSales[CustomerKey])), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ), FILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0 ))
73. 73. The Filter FormulaFilter only the customers…FILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0)
74. 74. The Filter FormulaWhere, for each of the filtered productsFILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0)
75. 75. The Filter FormulaThe number of rows in the fact table for that productFILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0)
76. 76. The Filter FormulaIs greater than zeroFILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0)
77. 77. The Filter FormulaThese conditions are needed because there aren’t relationshipsbetween Filter and the fact table. Thus, we add them manually in DAXFILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0)
78. 78. Ok, but «NotHavingProduct»?The filter conditions are identical, the only change is in the formulacomputed by CALCULATENotHavingProduct := CALCULATE ( COUNTROWS ( FILTER ( Instead of: DimCustomer, CALCULATE (COUNTROWS (FactSales)) = 0 COUNTROWS ( ) ), DISTINCT (FactSales[CustomerKey]) FILTER ( ) ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ), FILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0 ))
79. 79. Nice, and the many-to-many?This is a nice demo, but why do you speak about it in a many-to-manysession?NotHavingProduct := CALCULATE ( COUNTROWS ( FILTER ( DimCustomer, CALCULATE (COUNTROWS (FactSales)) = 0 1° M2M Pattern ) ), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ), FILTER ( DimCustomer, SUMX ( ProductFilter, CALCULATE ( COUNTROWS (FactSales), ALL (FactSales), FactSales[CustomerKey] = EARLIER (DimCustomer[CustomerKey]), 2° M2M Pattern FactSales[ProductKey] = EARLIER (ProductFilter[ProductKey]), FILTER ( ALL (DimTime), DimTime[TimeKey] <= MAX (DimTime[TimeKey]) ) ) ) > 0 ))
80. 80. SQL 2012 New Features• Multiple relationships between tables o Role Dimensions o Role Keys• Active / Inactive relationships• USERELATIONSHIP o New filter function o Selects a model relationship to use in calculations• These additions make the data model much easier
81. 81. Inactive Relationships in Denali Inactive Relationships
82. 82. The Formula with DenaliCOUNTROWS ( FILTER ( DimCustomer, CALCULATE ( COUNTROWS (FactSales), USERELATIONSHIP ( Factsales[ProductKey], ProductFilter[ProductKey]) ) > 0 && CALCULATE ( COUNTROWS (FactSales), USERELATIONSHIP ( Factsales[ProductKey], DimProduct[ProductKey]) ) = 0 ))
83. 83. The formula with SQL 2012• Shorter• Somehow Faster• Much clearer o Shows the real intentions of the author• Key Point o It can be written by Excel Users o It is straightforward, no complex and geeky logic• In this example, Denali moves toward the users
84. 84. The formula pattern in SQL 2012In SQL 2012 avoid iterators like FILTER, rely on SUMMARIZE which ismuch faster and (when you learn it) easier to read Dim_Date PK ID_Date Date Many to Many Account – Customer AmountM2M := PK Fact_Transaction ID_Transaction Dim_Account Bridge_AccountCustomer PK,FK1 ID_Account PK ID_Account FK1 ID_Account PK,FK2 ID_Customer FK3 ID_Type CALCULATE ( FK2 ID_Date Account Amount SUM (Fact_Transaction[Amount]), SUMMARIZE ( Dim_Type Dim_Customer Bridge_AccountCustomer, PK ID_Type PK ID_Customer DimAccount[ID_Account] Type CustomerName ) ) 84
85. 85. M2M Pattern Outside FormulasIn SQL 2012, when querying in DAX you can sometimes use anoptimized pattern to handle many-to-many relationships EVALUATE CALCULATETABLE ( ADDCOLUMNS ( CROSSJOIN ( VALUES (Dim_Type), VALUES (Dim_Date) ), “SumOfAmount”, CALCULATE (SUM (Fact_Transaction[Amount])), “AvgOfAmount”, CALCULATE (AVG (Fact_Transaction[Amount])), ), SUMMARIZE ( Bridge_AccountCustomer, The filter works on both formulas at DimAccount[ID_Account] once. ) ) The inner formulas automatically apply the outer m2m filter. 85
86. 86. Basket Analysis: Conclusions• Modeled with the many to many pattern o Fact table as a bridge one o Relationships set in DAX• Very Powerful• Search for missing values o «Easy» as searching for existing ones
87. 87. No support for M2M in Tabular• Multidimensional handles M2M relationships.• Tabular does not (apparently)• DAX is the key to handle them• Many interesting models can be created leveraging DAX and the many to many patterns
88. 88. Conclusions• Many To Many Relationships o Can be handled in Tabular o Even if not very easily• Very Powerful o Cascading Many To Many o Survey Data Model o Basket Analysis• SQL 2012 new features o USERELATIONSHIP o SUMMARIZE
89. 89. Links• SQLBI Website www.sqlbi.com• PowerPivot Workshop www.powerpivotworkshop.com• Alberto Ferrari blog www.sqlblog.com/blogs/alberto_ferrari• Marco Russo blog www.sqlblog.com/blogs/marco_russo• For any question contact us at info@sqlbi.com
90. 90. Questões?