Gần đây chúng tôi đã tạo một mô hình bảng SSAS để người dùng của chúng tôi có thể truy cập nó thông qua PowerView. Chúng tôi có một số đo trên một trong các bảng thực tế của mình để TotalActiveItems
sử dụng công thức:
TotalActive:=COUNTAX(FILTER('Stats', ISBLANK([DeactDate]) = TRUE), 1)
Điều này hoạt động rất tốt khi cần thiết nhưng bây giờ chúng tôi có một yêu cầu để có được 10 phụ huynh hàng đầu cho mỗi tháng trong TotalActive
.
Để tham khảo, đây là một phần của mô hình của chúng tôi:
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 với các bảng và dữ liệu mẫu.
Các factStats
bảng có FKS đến DevID
, CustID
, BillDateTimeID
, và ParentID
. Yêu cầu mà chúng tôi có là tính toán hoặc lưu trữ Top 10 Parents
cho từng cái BillDateTimeID
dựa trên TotalActive
AND bao gồm mọi thứ không nằm trong Top 10 trong danh mục cuộn lên tương tự như sau:
+----------------+------------+------+
| BillDateTimeID | Parent | Rank |
+----------------+------------+------+
| 20140801 | Jim | 1 |
| 20140801 | Bob | 2 |
| 20140801 | All Others | 3 |
+----------------+------------+------+
Tôi có thể dễ dàng thực hiện điều này trong SQL bằng các hàm cửa sổ nhưng cố gắng tái tạo điều này cho SSAS là khó khăn. Trong SQL, chúng tôi sẽ nhận được kết quả bằng cách sử dụng:
;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;
Tôi đã thử nhiều cách khác nhau để có kết quả nhưng mỗi cách đều có một vấn đề. Những nỗ lực của tôi là dưới đây.
Ban đầu, tôi có thể lấy phần nào dữ liệu bằng truy vấn MDX nhưng sau đó không biết làm thế nào để kết hợp dữ liệu này vào mô hình bảng của chúng tôi. Truy vấn MDX để tham khảo là:
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]};
Tất nhiên, điều này cũng chỉ cho tôi kết quả trong một tháng chứ không phải mỗi tháng.
Khi tôi nhận ra rằng truy vấn MDX sẽ không hoạt động, tôi đã bắt đầu bằng cách thay đổi factStats
bảng của chúng tôi để bao gồm một cột mới để gắn cờ các mục trong Top 10 và trong giá trị cuộn lên.
alter table factStats
add Top10ParentID INT NOT NULL
constraint DF_factStats default (0);
Ràng buộc mặc định tham chiếu giá trị "Đã cuộn" của chúng tôi cho Top 10.
Nỗ lực số 1: Tôi đã tạo bảng Top 10 mới để lưu trữ ParentID, tên và Xếp hạng:
create table dimTop10Parent
(
Top10ParentID INT NOT NULL PRIMARY KEY,
ParentName varchar(100) NOT NULL,
Parent_Rank INT NOT NULL
);
Bảng này sau đó sẽ được điền mỗi lần chúng tôi làm mới mô hình của mình với Top 10 Cha mẹ mới dựa trên các mục Tổng số hoạt động mà họ có. Các Parent_Rank
sau đó cột được ẩn trong mô hình bảng của chúng tôi và sử dụng độc quyền để phân loại. Điều này hoạt động rất tốt, ngoại trừ chúng tôi không có khả năng trong lịch sử để có được Top 10 vì nó không dựa trên cơ sở hàng tháng.
Nỗ lực số 2: Tạo một bảng mới để lưu trữ Top 10 nhưng KHÓA CHÍNH sẽ bao gồm cả Top10ParentID và BillingDateTimeID.
create table dimTop10Parent
(
Top10ParentID INT NOT NULL,
ParentName varchar(100) NOT NULL,
Parent_Rank INT NOT NULL,
BillDateTimeID BIGINT NOT NULL
);
Vấn đề với điều này là chúng ta không thể tạo mối quan hệ giữa FK đơn thực tế với PK hai phần trong dimTop10Parent trong mô hình dạng bảng.
Nỗ lực số 3: Tạo bảng mới nhưng sử dụng danh tính làm 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
);
Các factStats
bảng sẽ lưu trữ các Top10ID
giá trị đó sẽ là duy nhất cho mỗi hàng. Tôi nghĩ rằng điều này sẽ giải quyết vấn đề của tôi, nhưng, không phải vì chúng ta không còn có thể sắp xếp theo Parent_Rank
mô hình, nó đã gây ra lỗi:
Không thể sắp xếp ParentName theo Parent_Rank vì ít nhất một giá trị trong ParentName có nhiều giá trị riêng biệt trong Parent_Rank. Ví dụ: bạn có thể sắp xếp [Thành phố] theo [Vùng] vì chỉ có một vùng cho mỗi thành phố, nhưng bạn không thể sắp xếp [Vùng] theo [Thành phố] vì có nhiều thành phố cho mỗi vùng.
Sử dụng dữ liệu mẫu, kết quả cuối cùng sẽ tương tự (phần này hiển thị Top 2 với cuộn thứ 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 |
Tại thời điểm này, tôi không biết làm thế nào để có được kết quả cuối cùng này. Tôi có thể thay đổi các bảng khi cần để lấy nó, tôi có thể thay đổi mô hình bằng cách sử dụng công thức, số đo, v.v. Tôi đã đọc về xếp hạng bằng các công thức DAX 1 , 2 , 3 nhưng dường như tôi không thể quấn đầu chúng đủ để có thể có được kết quả chính xác.
Làm cách nào tôi có thể tính toán / lưu trữ Top 10 này trong bất kỳ tháng nào mà vẫn có thể ghép dữ liệu khi cần trong mô hình bảng của chúng tôi?