内部联接的最新日期的T-SQL子查询

时间:2011-10-29 07:39:55

标签: tsql

我想做一个像这样的人类似的事情: T-SQL Subquery Max(Date) and Joins

我必须用n:m关系来做这件事。

所以布局是:

tbl_Opportunity
tbl_Opportunity_tbl_OpportunityData
tbl_OpportunityData

所以当你看到有一个交叉表连接机会与opportunitydata。 每个机会都有多个机会数据。在我看来,我只想要一个包含所有机会的列表和来自最新机会数据的数据。

我试过这样的事情:

SELECT     
    dbo.tbl_Opportunity.Id, dbo.tbl_Opportunity.Subject, 
    dbo.tbl_User.UserName AS Responsible, dbo.tbl_Contact.Name AS Customer, 
    dbo.tbl_Opportunity.CreationDate, dbo.tbl_Opportunity.ActionDate AS [Planned Closure], 
    dbo.tbl_OpportunityData.Volume, 
    dbo.tbl_OpportunityData.ChangeDate, dbo.tbl_OpportunityData.Chance
FROM         
    dbo.tbl_Opportunity 
INNER JOIN
    dbo.tbl_User ON dbo.tbl_Opportunity.Creator = dbo.tbl_User.Id 
INNER JOIN
    dbo.tbl_Contact ON dbo.tbl_Opportunity.Customer = dbo.tbl_Contact.Id 
INNER JOIN
    dbo.tbl_Opprtnty_tbl_OpprtnityData ON dbo.tbl_Opportunity.Id = dbo.tbl_Opprtnty_tbl_OpprtnityData.Id 
INNER JOIN
    dbo.tbl_OpportunityData ON dbo.tbl_Opprtnty_tbl_OpprtnityData.Id2 = dbo.tbl_OpportunityData.Id

问题是我的视图现在包含每个机会数据的行,因为我不知道如何过滤我只想要最新的数据。

你能帮帮我吗?我的问题描述是否足够清楚?

提前谢谢:-) 最好的祝愿, 月桂精

2 个答案:

答案 0 :(得分:1)

; WITH Base AS (
    SELECT     dbo.tbl_Opportunity.Id, dbo.tbl_Opportunity.Subject, dbo.tbl_User.UserName AS Responsible, dbo.tbl_Contact.Name AS Customer, 
                      dbo.tbl_Opportunity.CreationDate, dbo.tbl_Opportunity.ActionDate AS [Planned Closure], dbo.tbl_OpportunityData.Volume, 
                      dbo.tbl_OpportunityData.ChangeDate, dbo.tbl_OpportunityData.Chance
    FROM         dbo.tbl_Opportunity INNER JOIN
                      dbo.tbl_User ON dbo.tbl_Opportunity.Creator = dbo.tbl_User.Id INNER JOIN
                      dbo.tbl_Contact ON dbo.tbl_Opportunity.Customer = dbo.tbl_Contact.Id INNER JOIN
                      dbo.tbl_Opprtnty_tbl_OpprtnityData ON dbo.tbl_Opportunity.Id = dbo.tbl_Opprtnty_tbl_OpprtnityData.Id INNER JOIN
                      dbo.tbl_OpportunityData ON dbo.tbl_Opprtnty_tbl_OpprtnityData.Id2 = dbo.tbl_OpportunityData.Id    
)

, OrderedByDate AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY ChangeDate DESC) RN FROM Base
)

SELECT * FROM OrderedByDate WHERE RN = 1

为了使其更具可读性,我正在使用CTE(WITH部分)。最后,真正的“技巧”是ROW_NUMBER()tbl_Opportunity.Id对数据进行分区,然后按ChangeDate DESC排序分区(我称之为RN)。显然,每个分区的最大日期为RN = 1,然后我们按RN过滤。

如果不使用CTE,它将是这样的:

SELECT * FROM (
    SELECT     dbo.tbl_Opportunity.Id, dbo.tbl_Opportunity.Subject, dbo.tbl_User.UserName AS Responsible, dbo.tbl_Contact.Name AS Customer, 
                      dbo.tbl_Opportunity.CreationDate, dbo.tbl_Opportunity.ActionDate AS [Planned Closure], dbo.tbl_OpportunityData.Volume, 
                      dbo.tbl_OpportunityData.ChangeDate, dbo.tbl_OpportunityData.Chance,
                      ROW_NUMBER() OVER (PARTITION BY dbo.tbl_Opportunity.Id ORDER BY dbo.tbl_OpportunityData.ChangeDate DESC) RN
    FROM         dbo.tbl_Opportunity INNER JOIN
                      dbo.tbl_User ON dbo.tbl_Opportunity.Creator = dbo.tbl_User.Id INNER JOIN
                      dbo.tbl_Contact ON dbo.tbl_Opportunity.Customer = dbo.tbl_Contact.Id INNER JOIN
                      dbo.tbl_Opprtnty_tbl_OpprtnityData ON dbo.tbl_Opportunity.Id = dbo.tbl_Opprtnty_tbl_OpprtnityData.Id INNER JOIN
                      dbo.tbl_OpportunityData ON dbo.tbl_Opprtnty_tbl_OpprtnityData.Id2 = dbo.tbl_OpportunityData.Id    
) AS Base WHERE RN = 1

答案 1 :(得分:0)

该声明可以进一步简化:

SELECT TOP 1 WITH TIES
    dbo.tbl_Opportunity.Id, dbo.tbl_Opportunity.Subject, dbo.tbl_User.UserName AS Responsible, 
    dbo.tbl_Contact.Name AS Customer, dbo.tbl_Opportunity.CreationDate, 
    dbo.tbl_Opportunity.ActionDate AS [Planned Closure], dbo.tbl_OpportunityData.Volume, 
    dbo.tbl_OpportunityData.ChangeDate, dbo.tbl_OpportunityData.Chance
FROM 
    dbo.tbl_Opportunity INNER JOIN
    dbo.tbl_User ON dbo.tbl_Opportunity.Creator = dbo.tbl_User.Id INNER JOIN
    dbo.tbl_Contact ON dbo.tbl_Opportunity.Customer = dbo.tbl_Contact.Id INNER JOIN
    dbo.tbl_Opprtnty_tbl_OpprtnityData ON dbo.tbl_Opportunity.Id = dbo.tbl_Opprtnty_tbl_OpprtnityData.Id INNER JOIN
    dbo.tbl_OpportunityData ON dbo.tbl_Opprtnty_tbl_OpprtnityData.Id2 = dbo.tbl_OpportunityData.Id    
ORDER BY 
    ROW_NUMBER() OVER (PARTITION BY dbo.tbl_Opportunity.Id ORDER BY dbo.tbl_OpportunityData.ChangeDate DESC);