{"id":1174,"date":"2019-06-02T12:11:00","date_gmt":"2019-06-02T10:11:00","guid":{"rendered":"https:\/\/cwiok.pl\/?p=1174"},"modified":"2019-06-02T12:13:15","modified_gmt":"2019-06-02T10:13:15","slug":"skumulowana-suma-po-produktach-w-daxie","status":"publish","type":"post","link":"https:\/\/cwiok.pl\/index.php\/pl\/2019\/06\/02\/skumulowana-suma-po-produktach-w-daxie\/","title":{"rendered":"Skumulowana suma po produktach w DAXie"},"content":{"rendered":"\r\n<p style=\"text-align: justify;\">To jest problem, kt\u00f3ry napotka\u0142em u jednego ze swoich klient\u00f3w bardzo niedawno. Chcia\u0142em policzy\u0107 jaka sprzeda\u017c jest generowana przez N pierwszych produkt\u00f3w w stylu pareto tj. je\u015bli pierwszy produkt ma sprzeda\u017c 200, a drugi 100, to dla pierwszego b\u0119d\u0119 mia\u0142 200, a dla drugiego 300. Taka kalkulacja pozwala pokaza\u0107, \u017ce przyk\u0142adowo 90% sprzeda\u017cy jest generowane przez 7 produkt\u00f3w.<\/p>\r\n<p><a href=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1188\" src=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal.png\" alt=\"\" width=\"1200\" height=\"628\" srcset=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal.png 1200w, https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal-300x157.png 300w, https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal-768x402.png 768w, https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal-1024x536.png 1024w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/p>\r\n<p style=\"text-align: justify;\">Pocz\u0105tkowo, wypr\u00f3bowa\u0142em podej\u015bcie z wykorzystaniem RANKX. Niestety ze wzgl\u0119du na wolumen danych (ponad 300 SKU wybieranych dynamicznie i miliony wierszy) wydajno\u015b\u0107 by\u0142a bardzo s\u0142aba. RANKX musia\u0142 by\u0107 obliczony wielokrotnie dla ka\u017cdej kom\u00f3rki z uwzgl\u0119dnieniem wszystkich wybranych produkt\u00f3w. Musia\u0142em znale\u017a\u0107 inny podej\u015bcie, i szcz\u0119\u015bliwie ten <a href=\"https:\/\/exceleratorbi.com.au\/cumulative-running-total-based-on-highest-value\/\">post<\/a> wskaza\u0142 mi drog\u0119. Miara, kt\u00f3rej ostatecznie u\u017cy\u0142em:<\/p>\r\n<p>Cumulative\u00a0Total\u00a0=<br \/><span class=\"Keyword\" style=\"color: #0070ff;\">VAR<\/span>\u00a0<span class=\"Variable\" style=\"color: #49b0af;\">total_sales<\/span>\u00a0=\u00a0[Total\u00a0Sales]<br \/><span class=\"Keyword\" style=\"color: #0070ff;\">RETURN<\/span><br \/><span class=\"indent4\">\u00a0\u00a0\u00a0\u00a0<\/span><span class=\"Keyword\" style=\"color: #0070ff;\">IF<\/span><span class=\"Parenthesis\" style=\"color: #969696;\">\u00a0(<\/span><br \/><span class=\"indent8\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span class=\"Keyword\" style=\"color: #0070ff;\">NOT<\/span><span class=\"Parenthesis\" style=\"color: #969696;\">\u00a0(<\/span>\u00a0<span class=\"Keyword\" style=\"color: #0070ff;\">ISBLANK<\/span><span class=\"Parenthesis\" style=\"color: #969696;\">\u00a0(<\/span>\u00a0<span class=\"Variable\" style=\"color: #49b0af;\">total_sales<\/span>\u00a0<span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span>\u00a0<span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span>,<br \/><span class=\"indent8\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span class=\"Keyword\" style=\"color: #0070ff;\">CALCULATE<\/span><span class=\"Parenthesis\" style=\"color: #969696;\">\u00a0(<\/span><br \/><span class=\"indent8\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span class=\"indent4\">\u00a0\u00a0\u00a0\u00a0<\/span>[Total\u00a0Sales],<br \/><span class=\"indent8\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span class=\"indent4\">\u00a0\u00a0\u00a0\u00a0<\/span><span class=\"Keyword\" style=\"color: #0070ff;\">FILTER<\/span><span class=\"Parenthesis\" style=\"color: #969696;\">\u00a0(<\/span>\u00a0<span class=\"Keyword\" style=\"color: #0070ff;\">ALLSELECTED<\/span><span class=\"Parenthesis\" style=\"color: #969696;\">\u00a0(<\/span>\u00a0Sales[Product]\u00a0<span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span>,\u00a0<span class=\"Variable\" style=\"color: #49b0af;\">total_sales<\/span>\u00a0&lt;=\u00a0[Total\u00a0Sales]\u00a0<span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span><br \/><span class=\"indent8\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/span><span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span><br \/><span class=\"indent4\">\u00a0\u00a0\u00a0\u00a0<\/span><span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span><\/p>\r\n<p>A to jak dzia\u0142a w akcji. Mam prost\u0105 tabel\u0119 z produktami i sprzeda\u017c\u0105:<\/p>\r\n<p><a href=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter  wp-image-1177\" src=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table.png\" alt=\"\" width=\"222\" height=\"213\" \/><\/a><\/p>\r\n<p>Tworz\u0119 miar\u0119 [Total Sales] = SUM(Sales[Sales]) i moj\u0105 miar\u0119 [Cumulative Total]. Po wrzuceniu ich do tabeli, otrzymuj\u0119:<\/p>\r\n<p><a href=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1178\" src=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-1.png\" alt=\"\" width=\"420\" height=\"275\" srcset=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-1.png 420w, https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-1-300x196.png 300w\" sizes=\"auto, (max-width: 420px) 100vw, 420px\" \/><\/a>I dok\u0142adnie tak jak chc\u0119, mam skumulowan\u0105 sprzeda\u017c licz\u0105c od najlepszego produktu. Przy wybraniu produkt\u00f3w B,F,C, otrzymuj\u0119:<\/p>\r\n<p><a href=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1179\" src=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-2.png\" alt=\"\" width=\"394\" height=\"220\" srcset=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-2.png 394w, https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-2-300x168.png 300w\" sizes=\"auto, (max-width: 394px) 100vw, 394px\" \/><\/a>Wi\u0119c, jak to dzia\u0142a?<\/p>\r\n<p><span class=\"Keyword\" style=\"color: #0070ff;\">VAR <\/span><span class=\"Variable\" style=\"color: #49b0af;\">total_sales<\/span> = [Total Sales]<\/p>\r\n<p>Ta cz\u0119\u015b\u0107 obliczy i &#8220;zapisze&#8221; sprzeda\u017c dla produktu z kontekstu filtra. Warto zwr\u00f3ci\u0107 uwag\u0119 na to, \u017ce zmianna jest obliczana raz przy deklaracji. W przyk\u0142adzie dla produkt\u00f3w B,F,C <span class=\"Variable\" style=\"color: #49b0af;\">total_sales<\/span> to kolejno 400,315,243.<\/p>\r\n<p><span class=\"Keyword\" style=\"color: #0070ff;\">IF<\/span><span class=\"Parenthesis\" style=\"color: #969696;\"> (<\/span><br \/><span class=\"Keyword\" style=\"color: #0070ff;\">NOT<\/span><span class=\"Parenthesis\" style=\"color: #969696;\"> (<\/span> <span class=\"Keyword\" style=\"color: #0070ff;\">ISBLANK<\/span><span class=\"Parenthesis\" style=\"color: #969696;\"> (<\/span> <span class=\"Variable\" style=\"color: #49b0af;\">total_sales<\/span> <span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span><span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span><\/p>\r\n<p>Ta cz\u0119\u015b\u0107 odsiewa produkty, kt\u00f3re nie maj\u0105 \u017cadnej sprzeda\u017cy.<\/p>\r\n<p><span class=\"Keyword\" style=\"color: #0070ff;\">CALCULATE<\/span><span class=\"Parenthesis\" style=\"color: #969696;\"> (<\/span>[Total Sales],<\/p>\r\n<p>Ta cz\u0119\u015b\u0107 policzy ca\u0142kowit\u0105 sprzeda\u017c dla produkt\u00f3w wybranych w filtrze w nast\u0119pnym kroku.<\/p>\r\n<p><span class=\"Keyword\" style=\"color: #0070ff;\">FILTER<\/span><span class=\"Parenthesis\" style=\"color: #969696;\"> (<\/span> <span class=\"Keyword\" style=\"color: #0070ff;\">ALLSELECTED<\/span><span class=\"Parenthesis\" style=\"color: #969696;\"> (<\/span> Sales[Product] <span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span>, <span class=\"Variable\" style=\"color: #49b0af;\">total_sales<\/span> &lt;= [Total Sales] <span class=\"Parenthesis\" style=\"color: #969696;\">)<\/span><\/p>\r\n<p style=\"text-align:justify;\">To jest najwa\u017cniejsza, ale te\u017c najdziwniejsza cz\u0119\u015b\u0107. Funkcja <a href=\"https:\/\/docs.microsoft.com\/en-us\/dax\/filter-function-dax\">FILTER<\/a> zwraca tabel\u0119, kt\u00f3ra reprezentuje podzbi\u00f3r innej tabeli lub wyra\u017cenia. W przypadku przyk\u0142adu pierwotn\u0105 tabel\u0105 jest <span class=\"Keyword\" style=\"color: #0070ff;\">ALLSELECTED<\/span><span class=\"Parenthesis\" style=\"color: #969696;\"> (<\/span> Sales[Product] <span class=\"Parenthesis\" style=\"color: #969696;\">).<\/span>a Nast\u0119pnie, funkcja przejdize przez ka\u017cdy element tabeli (w przyk\u0142adzie b\u0119dize to B,F,C) i sprawdzi czy total_sales (czyli zapisana warto\u015b\u0107 dla konkretnej kom\u00f3rki) jest mniejsza lub r\u00f3wna [Total Sales] dla elementu tabeli. Nast\u0119pnie funkcja wybiera tyle te elementy, kt\u00f3re spe\u0142niaj\u0105 warunek i liczy dla nich [Total Sales].<\/p>\r\n<p>To mo\u017ce wydawa\u0107 si\u0119 zagmatwane, wi\u0119c poka\u017c\u0119 to dok\u0142adnie na drugim przyk\u0142adzie:<\/p>\r\n<p><a href=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1179\" src=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-2.png\" alt=\"\" width=\"394\" height=\"220\" srcset=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-2.png 394w, https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/table-2-300x168.png 300w\" sizes=\"auto, (max-width: 394px) 100vw, 394px\" \/><\/a>Miara w DAX jest liczona oddzielnie dla ka\u017cdej kom\u00f3rki, poniewa\u017c znajduj\u0105 si\u0119 one w innych kontakstach filtra.\u00a0 Dlatego poka\u017c\u0119 oddzielne wyliczenia dla kom\u00f3rek C,F,B i jak osi\u0105gaj\u0105 warto\u015bci 958, 715 i 400.<\/p>\r\n<p>Obliczenia dla produktu C:<\/p>\r\n<p>total_sales (jak ju\u017c wyja\u015bni\u0142em wy\u017cej) b\u0119dzie r\u00f3wna\u0142o si\u0119 243<\/p>\r\n<p>NOT(ISBLANK(total_sales) to PRAWDA, poniewa\u017c 243 nie jest puste<\/p>\r\n<p>CALCULATE([Total Sales] zale\u017cy od tego co jest w filtrze<\/p>\r\n<p style=\"text-align:justify;\">FILTER(ALLSELECTED(Sales[Product]) ma ma\u0142\u0105 tabel\u0119 z kolumn\u0105 [Product] i wierszami C,F,B. Sprawdza dla ka\u017cdego wiersza czy [Total Sales] jest wi\u0119ksze lub r\u00f3wne ni\u017c 243. Dla C,[Total Sales] = 243, wi\u0119c warunek jest spe\u0142niony. Dla F, [Total Sales] = 315 te\u017c jest wi\u0119kszy ni\u017c 243. Dla B, [Total Sales] to 400, wi\u0119c jest wi\u0119kszy ni\u017c 243. Filtr przeka\u017ce wszystkie wiersze, a CALCULATE policzy [Total Sales] dla nich. Dlatego Cumulative Total to 243+315+400=958.<\/p>\r\n<p>&nbsp;<\/p>\r\n<p>Obliczenia dla produktu F:<\/p>\r\n<p>total_sales b\u0119dzie r\u00f3wna\u0142o si\u0119 315<\/p>\r\n<p>NOT(ISBLANK(total_sales) to PRAWDA, poniewa\u017c 315 nie jest puste<\/p>\r\n<p>CALCULATE([Total Sales] zale\u017cy od tego co jest w filtrze<\/p>\r\n<p style=\"text-align:justify;\">FILTER(ALLSELECTED(Sales[Product]) ma ma\u0142\u0105 tabel\u0119 z kolumn\u0105 [Product] i wierszami C,F,B. Sprawdza dla ka\u017cdego wiersza czy [Total Sales] jest wi\u0119ksze lub r\u00f3wne ni\u017c 315. Dla C,[Total Sales] = 243, wi\u0119c mniejszy ni\u017c 315. Warunek nie jest spe\u0142niony. Dla F, [Total Sales] = 315, wi\u0119c jest r\u00f3wny 315. Dla B, [Total Sales] to 400, wi\u0119c jest wi\u0119kszy ni\u017c 315. Filtr przeka\u017ce wiersze F i B, a CALCULATE policzy [Total Sales] dla nich. Dlatego Cumulative Total to 315+400=715.<\/p>\r\n<p>&nbsp;<\/p>\r\n<p>Obliczenia dla produktu B:<\/p>\r\n<p>total_sales b\u0119dzie r\u00f3wna\u0142o si\u0119 400<\/p>\r\n<p>NOT(ISBLANK(total_sales) to PRAWDA, poniewa\u017c 400 nie jest puste<\/p>\r\n<p>CALCULATE([Total Sales] zale\u017cy od tego co jest w filtrze<\/p>\r\n<p style=\"text-align:justify;\">FILTER(ALLSELECTED(Sales[Product]) ma ma\u0142\u0105 tabel\u0119 z kolumn\u0105 [Product] i wierszami C,F,B. Sprawdza dla ka\u017cdego wiersza czy [Total Sales] jest wi\u0119ksze lub r\u00f3wne ni\u017c 400. Dla C,[Total Sales] = 243, wi\u0119c mniejszy ni\u017c 400. Warunek nie jest spe\u0142niony. Dla F, [Total Sales] = 315, wi\u0119c te\u017c mniejszy ni\u017c total_sales (400). Warunek nie jest spe\u0142niony. Dla B, [Total Sales] to 400, wi\u0119c jest r\u00f3wny total_sales. Filtr przeka\u017ce wiersz B, a CALCULATE policzy [Total Sales] dla niego. Dlatego Cumulative Total to 400.<\/p>\r\n<p>Wydaje mi si\u0119, \u017ce jest to najwydajniejszy spos\u00f3b liczenia miary tego typu, szczeg\u00f3lnie, \u017ce nie polega na RANKX.<\/p>\r\n<p>Thanks,<\/p>","protected":false},"excerpt":{"rendered":"<p>To jest problem, kt\u00f3ry napotka\u0142em u jednego ze swoich klient\u00f3w bardzo niedawno. Chcia\u0142em policzy\u0107 jaka sprzeda\u017c jest generowana przez N pierwszych produkt\u00f3w w stylu pareto tj. je\u015bli pierwszy produkt ma sprzeda\u017c 200, a drugi 100, to dla pierwszego b\u0119d\u0119 mia\u0142 200, a dla drugiego 300. Taka kalkulacja pozwala pokaza\u0107, \u017ce przyk\u0142adowo 90% sprzeda\u017cy jest generowane przez 7 produkt\u00f3w.<\/p>\n<p><a href=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1188\" src=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal.png\" alt=\"\" width=\"1200\" height=\"628\" srcset=\"https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal.png 1200w, https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal-300x157.png 300w, https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal-768x402.png 768w, https:\/\/cwiok.pl\/wp-content\/uploads\/2019\/06\/cumtotal-1024x536.png 1024w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/p>\n<div class=\"tech_read_more\"><a href=\"https:\/\/cwiok.pl\/index.php\/pl\/2019\/06\/02\/skumulowana-suma-po-produktach-w-daxie\/\">Read More<\/a><\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[32],"tags":[],"class_list":["post-1174","post","type-post","status-publish","format-standard","hentry","category-powerbi-pl"],"_links":{"self":[{"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/posts\/1174","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/comments?post=1174"}],"version-history":[{"count":0,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/posts\/1174\/revisions"}],"wp:attachment":[{"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/media?parent=1174"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/categories?post=1174"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cwiok.pl\/index.php\/wp-json\/wp\/v2\/tags?post=1174"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}