2015-10-13 44 views
1

我使用SQL Server 2012,並具有以下表創建矩陣:所有日期和所有的用戶數量和類別

CREATE TABLE [dbo].[Users](
    [UserId] [bigint] NOT NULL 
) 
CREATE TABLE [dbo].[CategoryIds](
    [CategoryId] [int] NOT NULL 
) 
CREATE TABLE [dbo].[DimDate](
    [Year_Value] [int] NOT NULL, 
    [Month_Value] [int] NOT NULL 
) 
CREATE TABLE [dbo].[TransactionsData](
    [TransactionId] [int] NOT NULL, 
[UserId] [bigint] NOT NULL, 
[CategoryId] [int] NOT NULL, 
[Date] [datetime] NOT NULL 
) 

表中的數據是這樣的:

Insert into [dbo].[Users] 
select 1 union all 
select 2 union all 
select 3 


Insert into [dbo].[CategoryIds] 
select 1 union all 
select 2 union all 
select 5 

insert into [dbo].[DimDate] 
select 2015, 3 union all 
select 2015,4 

insert into [dbo].[TransactionsData] 
select 1,1,1,'2015-03-01' union all 
select 2,1,1,'2015-03-20' union all 
select 3,2,5,'2015-03-02' union all 
select 4,2,5,'2015-03-05' 

我想有一個T-SQL代碼生成這樣的表格:

CREATE TABLE [dbo].[Matrix](
[Year_Value] [int] NOT NULL, 
[Month_Value] [int] NOT NULL, 
[UserId] [bigint] NOT NULL, 
[TransactionCount] [bigint] NOT NULL, 
[1] [int] NOT NULL, -- category with id 1 
[2] [int] NOT NULL, -- category with id 2 
[5] [int] NOT NULL -- category with id 5 etc 
) 

而矩陣表包含一個記錄對於每個年份和月份的每個用戶,無論該月份是否有該用戶的任何交易。如果沒有事務,則Year和Month和UserID仍作爲記錄存在,但事務計數爲0.對類別同樣有效:每個CategoryId成爲Matrix表的一列,每列中都有一個計數每年,每月和每個用戶有多少交易屬於每個類別。如果沒有針對特定用戶和特定類別的交易,則相應列中的值爲0。

我已經試過什麼:

select d.*, u.UserId, isnull(t.TransactionId,0) 
from [dbo].[DimDate] d 
outer apply (select UserId from [dbo].[Users]) u 
full outer join [dbo].[TransactionsData] t on u.UserId = t.UserId 

的數據在矩陣表將這個樣子,因爲上面的表中的數據:

INSERT INTO [dbo].[Matrix] 
SELECT 2015, 3, 1, 2, 2, 0, 0 UNION ALL 
SELECT 2015, 3, 2, 2, 0, 0, 2 UNION ALL 
SELECT 2015, 3, 3, 0, 0, 0, 0 UNION ALL 
SELECT 2015, 4, 1, 0, 0, 0, 0 UNION ALL 
SELECT 2015, 4, 2, 0, 0, 0, 0 UNION ALL 
SELECT 2015, 4, 3, 0, 0, 0, 0 
+0

我嘗試這樣做: '選擇d *,u.UserId,ISNULL(t.TransactionId,0)從[DBO] [DimDate] d 外應用(從[DBO]選擇用戶ID [。用戶])ü 全外連接[dbo]。[TransactionsData] t on u.UserId = t.UserId' 但是有一些記錄丟失。這個想法是獲得所有的記錄,然後做交易和類別的數量樞軸。我在正確的軌道上嗎? – sibir1us

+0

您可以發佈樣本數據的預期結果嗎? –

+0

在給出上表中的數據的情況下,Matrix表中的數據將如下所示: INSERT INTO [dbo]。[Matrix] SELECT 2015,3,1,2,2,0,0 UNION ALL SELECT 2015,3,2,2,0,0,2 UNION ALL 選擇2015年3,3,0,0,0,0聯盟全部 選擇2015年4,1,0,0,0,0聯盟全部 SELECT 2015,4,2,0,0,0,0 UNION ALL SELECT 2015,4,3,0,0,0,0' – sibir1us

回答

1

您可以在此使用dynamic crosstab做:

SQL Fiddle

DECLARE @sql NVARCHAR(MAX) = '' 

SELECT @sql = 
'SELECT 
    a.Year_Value 
    , a.Month_Value 
    , a.UserId 
    , COUNT(td.TransactionId) AS TransactionCount' + CHAR(10) 

SELECT @sql = @sql + 
' , SUM(CASE WHEN CategoryId = ' + CONVERT(VARCHAR(10), CategoryId) + ' THEN 1 ELSE 0 END) AS ' + QUOTENAME(CategoryId) + CHAR(10) 
FROM CategoryIds 

SELECT @sql = @sql + 
'FROM (
    SELECT 
     u.UserId, dd.Year_Value, m.Month_Value 
    FROM(VALUES 
     (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12) 
    )m(Month_Value) 
    CROSS JOIN(
     SELECT DISTINCT Year_Value FROM DimDate 
    )dd 
    CROSS JOIN Users u 
) a 
LEFT JOIN TransactionsData td 
    ON td.UserId = a.UserId 
    AND MONTH(td.Date) = a.Month_Value 
    AND YEAR(td.Date) = a.Year_Value 
GROUP BY 
    a.Year_Value, a.Month_Value, a.UserId 
ORDER BY 
    a.UserId, a.Year_Value, a.Month_Value' 

PRINT @sql 
EXEC (@sql) 

的想法是生成所有可能的UserId - Year_Value - Month_Value組合。然後,使用生成的組合並在TransactionsData上執行LEFT JOIN

現在,要將CategoryIds顯示爲列,您需要執行條件聚合。這是非動態解決方案。這也是PRINT @sql命令的輸出。

SELECT 
    a.Year_Value 
    , a.Month_Value 
    , a.UserId 
    , COUNT(td.TransactionId) AS TransactionCount 
    , SUM(CASE WHEN CategoryId = 1 THEN 1 ELSE 0 END) AS [1] 
    , SUM(CASE WHEN CategoryId = 2 THEN 1 ELSE 0 END) AS [2] 
    , SUM(CASE WHEN CategoryId = 5 THEN 1 ELSE 0 END) AS [5] 
FROM (
    SELECT 
     u.UserId, dd.Year_Value, m.Month_Value 
    FROM(VALUES 
     (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12) 
    )m(Month_Value) 
    CROSS JOIN(
     SELECT DISTINCT Year_Value FROM DimDate 
    )dd 
    CROSS JOIN Users u 
) AS a 
LEFT JOIN TransactionsData td 
    ON td.UserId = a.UserId 
    AND MONTH(td.Date) = a.Month_Value 
    AND YEAR(td.Date) = a.Year_Value 
GROUP BY 
    a.Year_Value, a.Month_Value, a.UserId 
ORDER BY 
    a.UserId, a.Year_Value, a.Month_Value 
+0

它很棒。謝謝! – sibir1us

+0

很高興有幫助!如果您覺得這對您有用,請隨時接受我的回答。 :-) –

相關問題