วิธีการคำนวณ / จัดเก็บ 10 อันดับแรกในรูปแบบตาราง?


23

เราเพิ่งสร้างโมเดลตาราง SSAS เพื่อให้ผู้ใช้ของเราสามารถเข้าถึงได้ผ่าน PowerView เรามีมาตรการหนึ่งในตารางข้อเท็จจริงของเราเพื่อรับTotalActiveItemsสูตร:

TotalActive:=COUNTAX(FILTER('Stats', ISBLANK([DeactDate]) = TRUE), 1)

นี้ทำงานได้ดีตามความจำเป็น แต่ตอนนี้เรามีคำขอที่จะได้รับ Top 10 TotalActiveผู้ปกครองในแต่ละเดือนในส่วน

สำหรับการอ้างอิงนี่เป็นส่วนหนึ่งของแบบจำลองของเรา:

create table factStats
(
    StatsID INT IDENTITY NOT NULL PRIMARY KEY,
    DevID INT NOT NULL,
    DeactDate DATETIME NULL,
    BillDateTimeID BIGINT NOT NULL,
    CustID INT NOT NULL,
    ParentID INT NOT NULL
);

create table dimCust
(
    CustID INT NOT NULL PRIMARY KEY,
    CustName varchar(150) NOT NULL
);

create table dimParent
(
    ParentID INT NOT NULL PRIMARY KEY,
    ParentName varchar(100) NOT NULL
);

create table dimDateTime
(
    DateTimeID BIGINT NOT NULL PRIMARY KEY
);

ซอ Fiddleพร้อมโต๊ะและข้อมูลตัวอย่าง

factStatsตารางมี FKs ไปDevID, CustID, และBillDateTimeID ParentIDคำขอที่เรามีคือการคำนวณหรือจัดเก็บTop 10 Parentsสำหรับแต่ละรายการBillDateTimeIDตามTotalActive และรวมทุกอย่างที่ไม่อยู่ใน 10 อันดับแรกในหมวดหมู่สะสมที่คล้ายกับรายการต่อไปนี้:

+----------------+------------+------+
| BillDateTimeID |   Parent   | Rank |
+----------------+------------+------+
|       20140801 | Jim        |    1 |
|       20140801 | Bob        |    2 |
|       20140801 | All Others |    3 |
+----------------+------------+------+

ฉันสามารถทำสิ่งนี้ได้อย่างง่ายดายใน SQL โดยใช้ฟังก์ชั่นการเรียงหน้าต่าง แต่การพยายามทำซ้ำสิ่งนี้สำหรับ SSAS นั้นเป็นเรื่องยาก ใน SQL เราจะได้ผลลัพธ์โดยใช้:

;with Total as
(
  select 
    ParentID,
    BillDateTimeID,
    sum(case when DeactDate is null then 1 else 0 end) TotalActive
  from factStats
  group by ParentID, BillDateTimeID
),
PRank as
(
  select 
    ParentID,
    BillDateTimeID,
    TotalActive,
    row_number() over(partition by BillDateTimeID 
                      order by TotalActive desc) pr
  from total
)
select 
  parentid,
  BillDateTimeID,
  TotalActive,
  pr
from prank
where pr <= 2
union all
select 
  0,
  BillDateTimeID,
  sum(TotalActive) TotalActive,
  3
from prank
where pr > 2
group by BillDateTimeID
order by BillDateTimeID desc, pr;

SQL ซอสาธิต

ฉันลองหลายวิธีเพื่อให้ได้ผลลัพธ์ แต่แต่ละวิธีมีปัญหา ความพยายามของฉันอยู่ด้านล่าง

ในขั้นต้นฉันสามารถรับข้อมูลได้บ้างโดยใช้แบบสอบถาม MDX แต่ก็ไม่มีเงื่อนงำที่จะรวมสิ่งนี้เข้ากับแบบจำลองตารางของเรา แบบสอบถาม MDX สำหรับการอ้างอิงคือ:

with 
set [Top10Parent] AS
(
    (TOPCOUNT({ORDER(({[Parent].[Parent Name].[Parent Name]}),
        ([Measures].[Total Count]), BDESC)}, 10))
)
MEMBER [Parent].[Parent Name].[Others] AS
(
    AGGREGATE(EXCEPT([Parent].[Parent Name].[Parent Name], [Top10Parent]))
)
select 
    [Measures].[Total Count] on columns,
    {[Top10Parent]}+ {[Parent].[Parent Name].[Others]} on Rows
from [OurModel]
where {[Date and Time].[Month and Year].[Month and Year].[Jul 2014]};

แน่นอนนี่ยังให้ผลลัพธ์เพียงเดือนเดียวไม่ใช่ทุกเดือน

เมื่อฉันรู้ว่าแบบสอบถาม MDX ไม่ทำงานฉันเริ่มต้นด้วยการเปลี่ยนfactStatsตารางของเราเพื่อรวมคอลัมน์ใหม่เพื่อตั้งค่าสถานะรายการใน 10 อันดับแรกและในค่าสะสม

alter table factStats
    add Top10ParentID INT NOT NULL
    constraint DF_factStats default (0);

ข้อ จำกัด เริ่มต้นอ้างอิงค่า "Rolled Up" ของเราสำหรับ 10 อันดับแรก

ลอง # 1: ฉันสร้างตาราง 10 อันดับใหม่เพื่อเก็บ ParentID ชื่อและอันดับ:

create table dimTop10Parent
(
    Top10ParentID INT NOT NULL PRIMARY KEY,
    ParentName varchar(100) NOT NULL,
    Parent_Rank INT NOT NULL
);

จากนั้นตารางนี้จะถูกเติมแต่ละครั้งที่เรารีเฟรชโมเดลของเรากับผู้ปกครอง 10 อันดับใหม่ตามรายการรวมที่ใช้งานอยู่ Parent_Rankคอลัมน์ถูกซ่อนอยู่แล้วในรูปแบบตารางของเราและใช้เฉพาะสำหรับการจัดเรียง วิธีนี้ใช้งานได้ดียกเว้นว่าเราไม่มีความสามารถในการรับ 10 อันดับแรกในอดีตเพราะมันไม่ได้ขึ้นอยู่กับเดือนต่อเดือน

ลอง # 2:สร้างตารางใหม่เพื่อเก็บ Top 10 แต่คีย์หลักจะมีทั้ง Top10ParentID และ BillingDateTimeID

create table dimTop10Parent
(
    Top10ParentID INT NOT NULL,
    ParentName varchar(100) NOT NULL,
    Parent_Rank INT NOT NULL,
    BillDateTimeID BIGINT NOT NULL
);

ปัญหาเกี่ยวกับสิ่งนี้คือเราไม่สามารถสร้างความสัมพันธ์ระหว่าง factStats FK เดี่ยวกับ PK สองส่วนใน dimTop10Parent ในโมเดลตาราง

ลอง # 3:สร้างตารางใหม่ แต่ใช้ข้อมูลประจำตัวเป็น PK

create table dimTop10Parent
(
    Top10ID INT IDENTITY NOT NULL PRIMARY KEY,
    Top10ParentID INT NOT NULL,
    ParentName varchar(100) NOT NULL,
    Parent_Rank INT NOT NULL,
    BillDateTimeID BIGINT NOT NULL
);

factStatsตารางจะเก็บTop10IDค่าซึ่งจะไม่ซ้ำกันในแต่ละแถว ฉันคิดว่าสิ่งนี้จะแก้ปัญหาของฉันได้ แต่ไม่ใช่เพราะเราไม่สามารถเรียงลำดับตามParent_Rankในโมเดลได้อีกต่อไปมันส่งข้อผิดพลาด:

ไม่สามารถเรียงลำดับ ParentName โดย Parent_Rank เพราะอย่างน้อยหนึ่งค่าใน ParentName มีหลายค่าที่แตกต่างใน Parent_Rank ตัวอย่างเช่นคุณสามารถจัดเรียง [เมือง] ตาม [ภูมิภาค] เนื่องจากมีเพียงภูมิภาคเดียวสำหรับแต่ละเมือง แต่คุณไม่สามารถจัดเรียง [ภูมิภาค] ตาม [เมือง] เนื่องจากมีหลายเมืองในแต่ละภูมิภาค

การใช้ข้อมูลตัวอย่างผลลัพธ์สุดท้ายควรคล้ายกับ (ซึ่งแสดงให้เห็น 2 อันดับแรกที่มีการสะสมครั้งที่ 3):

| PARENTNAME | BILLDATETIMEID | TOTALACTIVE | PR |
|------------|----------------|-------------|----|
|     FDN    |   201408010000 |          11 |  1 |
|     FDO    |   201408010000 |           3 |  2 |
| All Others |   201408010000 |           5 |  3 |
|     FDN    |   201407010000 |          12 |  1 |
|     EVOD   |   201407010000 |           2 |  2 |
| All Others |   201407010000 |           5 |  3 |

เมื่อมาถึงจุดนี้ฉันกำลังสูญเสียเกี่ยวกับวิธีการรับผลสุดท้ายนี้ ฉันสามารถเปลี่ยนตารางได้ตามต้องการฉันสามารถเปลี่ยนแบบจำลองโดยใช้สูตรการวัดและอื่น ๆ ฉันได้อ่านเกี่ยวกับการจัดอันดับโดยใช้สูตร DAX 1 , 2 , 3แต่ฉันไม่สามารถคาดศีรษะได้ พวกเขาเพียงพอที่จะสามารถรับผลลัพธ์ได้อย่างถูกต้อง

ฉันจะคำนวณ / เก็บ 10 อันดับแรกนี้สำหรับเดือนใด ๆ และยังสามารถแยกข้อมูลตามที่ต้องการในโมเดลตารางของเราได้อย่างไร

คำตอบ:


1

ฉันมีสถานการณ์ที่คล้ายกันและใช้เคียวรี DAX ต่อไปนี้ ...

ก่อนอื่นเพื่อให้ง่ายฉันได้กำหนดมาตรการที่จะใช้ภายใน DAX ดังนั้นฉันจึงไม่ต้องทำซ้ำสูตร จากนั้นฉันใช้สร้างเพื่อทำซ้ำในสูตร TOPN:

define measure TableInTabular[NameOfTheMeasure] = COUNTAX(FILTER('Stats', ISBLANK([DeactDate]) = TRUE), 1)
evaluate
 (
  addcolumns
   (  
    filter
     (  
      generate
        (  
         VALUES(DatesTableName[Month]),  
         TOPN (10, VALUES(TableInTabular[ParentID]),TableInTabular[NameOfTheMeasure],0)
        ),
        TableInTabular[NameOfTheMeasure]>0
      ),
      "ActiveCount (or how you want to call this Column)",
      TableInTabular[NameOfTheMeasure]  
    )  
 )  
order by DatesTableName[Month] asc, 
TableInTabular[NameOfTheMeasure] desc

ด้วยข้างต้นคุณควรมี ParentID 10 อันดับแรกและการวัดโดยในแต่ละเดือน เพียงแค่แทนที่ "TableInTabular" ด้วยชื่อตารางแบบตารางของคุณซึ่งคุณมีข้อมูลและ "DatesTableName" ด้วยชื่อของตารางวันที่

โปรดแจ้งให้เราทราบหากฉันเข้าใจผิดคำถามของคุณและหวังว่าจะช่วย ...


1
ขอขอบคุณสำหรับคำตอบยังมีปัญหาบางประการเกี่ยวกับเรื่องนี้ อันดับแรกฉันสามารถใช้สิ่งนี้ภายใน SSMS แต่สิ่งนี้กำลังถูกปรับใช้ในโมเดลแบบตารางของเราเพื่อให้ผู้ใช้ของเราสามารถเข้าถึงได้ผ่าน PowerView - พวกเขาจะไม่เขียนคำถามใด ๆ ประการที่สองถ้าฉันทำสิ่งผิดปกติจะไม่มีการประเมินหรือคำสั่งซื้อที่อนุญาตในโมเดลแบบตารางผ่าน Visual Studio - ไม่มีตัวเลือกสำหรับสิ่งนี้เป็นฟังก์ชั่น ประการที่สามการสืบค้นนี้ส่งคืน 10 อันดับแรกเท่านั้นฉันต้องการข้อมูลสะสมหรือวิธีการอื่น ฉันจะเล่นต่อไปกับสิ่งนี้แม้ว่า
Taryn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.