2016-12-02 53 views
0

我正在创建我认为将SQL中的2个新表。这个想法是一个是“实时”数据,另一个是保持所有变化。日期为DD/MM/YYYY格式。关于某个时间点的报告

Active 
ID | Name | State Date | End Date 
1 Zac 1/1/2016  -   
2 John 1/5/2016  -   
3 Sam 1/6/2016  -   
4 Joel 1/7/2016  -   

Changes 
CID | UID | Name | Start Date | End Date 
1  1  Zac 1/1/2016  - 
2  4  Joel 1/1/2016  - 
3  4  Joel -   1/4/2016  
4  2  John 1/5/2016  - 
5  3  Sam 1/6/2016  - 
6  4  Joel 1/7/2016  - 

在上述情况下,你可以看到,乔尔从2016年1月1日一直工作到2016年1月4日,了3个月关闭,然后从2016年1月7日的工作。

我需要建立一个查询,我可以在那里及时选择一个日期并报告当时谁在工作。上表仅列出名称,但在某个时间点上还会有更多列进行报告。

什么是最好的方式来构建表,以便能够实现此查询。

+2

这里是关于不同的渐变维度的好文章SCD类型和结构可能会根据其他用途和要求将其保存在同一张表中,从而简化您的生活。 https://en.wikipedia.org/wiki/Slowly_changing_dimension – Matt

+0

将有一个阅读。谢谢! – Zac

+3

您所选择的DBMS可能对此类任务有一些内置支持。例如,SQL Server 2016实现了[Temporal tables](https://msdn.microsoft.com/en-us/library/dn935015.aspx)。 –

回答

0

我开始写这个昨晚,最后回到它。基本上,你将不得不使用你的变化表创建一个渐变维度,然后生成一个行号来匹配你的开始和结束。但是,这将假设您的数据库将永远不会通过在一行中添加2个开始记录或2个结束记录而不同步。

这还假定您使用的是支持公共表表达式和窗口功能,如SQL服务器,Oracle,PostgreSQL的,DB2关系数据库....

WITH cte AS (
    SELECT 
     * 
     ,ROW_NUMBER() OVER (PARTITION BY UID ORDER BY ISNULL(StartDate,EndDate)) As RowNum 
    FROM 
     Changes c 
) 

SELECT 
    s.UID 
    ,s.Name 
    ,s.StartDate 
    ,COALESCE(e.EndDate,GETDATE()) as EndDate 
FROM 
    cte s 
    LEFT JOIN cte e 
    ON s.UID = e.UID 
    AND s.RowNum + 1 = e.RowNum 
WHERE 
    s.StartDate IS NOT NULL 
    AND '2016-05-05' BETWEEN s.StartDate AND COALESCE(e.EndDate,GETDATE())