테이블 형식 모델에서 Top 10을 계산 / 저장하는 방법은 무엇입니까?


23

최근에 사용자가 PowerView를 통해 액세스 할 수 있도록 SSAS 테이블 형식 모델을 만들었습니다. 팩트 테이블 중 하나에 TotalActiveItems대한 공식을 사용하여 측정 값을 얻습니다 .

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

이것은 필요에 따라 훌륭하게 작동하지만 이제 월간 상위 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
);

테이블 및 샘플 데이터가있는 SQL Fiddle

factStats표에 FKS가 DevID, CustID, BillDateTimeID,와 ParentID. AND 에 따라 Top 10 Parents각각에 대해를 계산하거나 저장하라는 요청 은 다음과 유사한 롤업 범주의 상위 10에 포함되지 않은 모든 항목을 포함합니다.BillDateTimeIDTotalActive

+----------------+------------+------+
| 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 쿼리가 작동하지 않는다는 것을 깨달았을 때 factStatsTop 10 및 롤업 값에 항목을 표시하는 새 열을 포함하도록 테이블을 변경하여 시작했습니다 .

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

기본 구속 조건은 상위 10에 대한 "롤업"값을 참조합니다.

시도 # 1 : ParentID, 이름 및 순위를 저장하기 위해 새로운 Top 10 테이블을 만들었습니다.

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

그런 다음이 테이블은 보유한 총 활성 항목을 기준으로 새 상위 10 개 상위로 모델을 새로 고칠 때마다 채워집니다. Parent_Rank열은 우리의 테이블 형식 모델에 숨겨진 및 정렬을 위해 독점적으로 사용된다. 이것은 월 단위로 기반을 두지 않기 때문에 역사적으로 Top 10을 얻을 수있는 능력이 없다는 것을 제외하고는 훌륭하게 작동합니다.

시도 # 2 : 상위 10 개를 저장할 새 테이블을 작성하지만 기본 키에는 Top10ParentID와 BillingDateTimeID가 모두 포함됩니다.

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

이 문제는 테이블 형식 모델의 dimTop10Parent에서 factStats 단일 FK와 두 부분 PK 간의 관계를 만들 수 없다는 것입니다.

시도 # 3 : 새 테이블을 작성하지만 ID를 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에서 여러 개의 고유 값을 가지므로 Parent_Rank로 ParentName을 정렬 할 수 없습니다. 예를 들어, 도시마다 지역이 하나뿐이므로 [도시]를 [지역]별로 정렬 할 수 있지만 각 지역마다 도시가 여러 개 있으므로 [도시]를 기준으로 [지역]을 정렬 할 수 없습니다.

샘플 데이터를 사용하여 최종 결과는 다음과 유사해야합니다 (이것은 세 번째 롤업으로 상위 2를 표시 함).

| 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을 사용한 순위에 대해 읽었 지만 머리를 감쌀 수는 없습니다 정확하게 결과를 얻을 수있을 정도로

한 달 동안이 Top 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

위와 같이 매월 상위 10 개의 ParentID와 측정 값이 있어야합니다. "TableInTabular"를 데이터가있는 테이블 형식 테이블 이름으로 바꾸고 "DatesTableName"을 날짜 테이블 이름으로 바꿉니다.

귀하의 질문을 잘못 이해하고 도움이되기를 바랍니다.


1
답변 주셔서 감사합니다, 여전히 몇 가지 문제가 있습니다. 먼저 SSMS 내에서 이것을 사용할 수 있지만 이것은 테이블 형식 모델에 배포되어 사용자가 PowerView를 통해 액세스 할 수 있습니다. 쿼리를 작성하지 않을 것입니다. 둘째, 내가 잘못하고 있지 않는 한 Visual Studio를 통해 테이블 ​​형식 모델에서 허용되는 평가 또는 순서는 없습니다-함수로 사용할 수있는 옵션이 없습니다. 셋째,이 쿼리는 상위 10 만 반환하며 롤업 된 데이터 또는 가져 오는 방법이 필요합니다. 그래도 나는 이것으로 계속 놀 것이다.
Taryn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.