基于具有不相关表

时间:2015-08-28 18:02:11

标签: sql join sql-server-2012 birt

我需要根据具有一些中等复杂连接的查询中的行值来获取不相关表中的记录数。所有数据都位于单个SQL 2012数据库中的一台服务器上,位于几个不同的表上。

我正在从审核记录中重新创建单个故障单的故障单移动历史记录,并且需要计算由连接创建的行中的跨度的工作日。门票在区域之间移动(分配),并且有关于在任何一个区域应该有多长时间的指南。每次重新开始计时时,票证可能会多次到达同一区域。

我需要在工作日计算中考虑公司假期。在查看SE上的工作日计算的几个解决方案之后,我决定使用公司日历表(dbo.UPMCCALENDARM1)并计算跨度之间的日期。看起来像个好主意...

我无法弄清楚如何将行值用作日期计数查询的参数。

下面的查询具有带变量和交叉连接的工作解决方案,但它仅适用于硬编码日期,如果我尝试使用它不起作用的字段值,因为它们不是子查询的一部分,无法约束。

  

- 在DV_im_Audit_ASSIGNMENT.Time和Detail.RESOLVED_TIME之间

理论上我可以在子查询中使用这个完整的查询来获取日期计数,但这是我可以做到的最短并且仍然可以得到干净的数据。对于按需报告而言,这是一个相当沉重的提升,这将是我的最后选择。因此,我希望在列出每次出现的DV_im_Audit_ASSIGNMENT.Time和Detail.RESOLVED_TIME时联系UPMCCALENDARM1。

可以吗?如果是这样的话?

declare @NonBus integer 
set @NonBus = '0'
set @NonBus = (select Count(UPMCCALENDARM1.DATE) as NonBus
            from dbo.UPMCCALENDARM1
            where UPMC_BUSINESS_DAY = 'f'
            and UPMCCALENDARM1.DATE 
            between '2015-08-01' and '2015-08-31'
--          between DV_im_Audit_ASSIGNMENT.Time and Detail.RESOLVED_TIME
            )

select DV_im_Audit_ASSIGNMENT.Incident_ID
, DV_im_Audit_ASSIGNMENT.Old_ASSIGNMENT
, DV_im_Audit_ASSIGNMENT.New_ASSIGNMENT
, DV_im_Audit_ASSIGNMENT.Time as Assign_Time
, B.Time as Reassign_Time
, Detail.OPEN_TIME
, Cal.NonBus
, NonBus
, Detail.RESOLVED_TIME
, A.rownumA
, B.rownumB

from dbo.DV_im_Audit_ASSIGNMENT

--Get RownumA as a select join so I can work with it here, else get an invalid column name 'rownumA' error
left join(select Incident_ID
        , Old_ASSIGNMENT
        , New_ASSIGNMENT
        , [Time]
        , rownumA = ROW_NUMBER() OVER (ORDER BY  DV_im_Audit_ASSIGNMENT.Incident_ID, DV_im_Audit_ASSIGNMENT.Time)
        from dbo.DV_im_Audit_ASSIGNMENT
        where Incident_ID = ?
        ) as A
            on DV_im_Audit_ASSIGNMENT.Incident_ID = A.Incident_ID
            and DV_im_Audit_ASSIGNMENT.New_ASSIGNMENT = A.New_ASSIGNMENT
            and DV_im_Audit_ASSIGNMENT.Time = A.Time 

--Get time assigned to next group, is problomatic when assigned to the same group multiple times.
left join(select Incident_ID
        , Old_ASSIGNMENT
        , New_ASSIGNMENT
        , [Time]
        , rownumB = ROW_NUMBER() OVER (ORDER BY  DV_im_Audit_ASSIGNMENT.Incident_ID, DV_im_Audit_ASSIGNMENT.Time)
        from dbo.DV_im_Audit_ASSIGNMENT
        where Incident_ID = ?
        ) as B
            on DV_im_Audit_ASSIGNMENT.Incident_ID = B.Incident_ID
            and DV_im_Audit_ASSIGNMENT.New_ASSIGNMENT = B.Old_ASSIGNMENT
            and DV_im_Audit_ASSIGNMENT.Time < B.Time 
        and rownumA = (B.rownumB - 1)  

--Get current ticket info
left join (select Incident_ID
        , OPEN_TIME
        , RESOLVED_TIME
        from dbo.DV_im_PROBSUMMARYM1_Detail
        where Incident_ID = ?
        ) as Detail 
    on DV_im_Audit_ASSIGNMENT.Incident_ID = Detail.Incident_ID


--Count non-bussiness days.  This section is in testing and does not use dataview as a source.
-- this gets the date count for one group of dates, need a different count for each row based on assign time. 
cross join (Select Count(UPMCCALENDARM1.DATE) as NonBus
            from dbo.UPMCCALENDARM1
            where UPMC_BUSINESS_DAY = 'f'
            and UPMCCALENDARM1.DATE 
            between '2015-08-01' and '2015-08-30'
--          between DV_im_Audit_ASSIGNMENT.Time and Detail.RESOLVED_TIME
            ) as Cal


--Get data for one ticket
where DV_im_Audit_ASSIGNMENT.Incident_ID = ?

ORDER BY  DV_im_Audit_ASSIGNMENT.Incident_ID, DV_im_Audit_ASSIGNMENT.Time

结果 enter image description here

仅供参考 - 我通过BIRT 4.2运行此SQL,我相信很少有SQL项目无法通过BIRT

1 个答案:

答案 0 :(得分:0)

根据@Dominique的建议,我创建了一个自定义标量函数(使用SSMS中的向导),我使用默认值作为我通过使用存储过程开始的日期,这使得它更容易测试。此问题需要一个函数,因为它将返回每行的值,而存储过程不会。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      James Jenkins
-- Create date: September 2015
-- Description: Counts Business Days for UPMC during a span of dates
-- =============================================
CREATE FUNCTION dbo.UPMCBusinessDayCount 
(
    -- Add the parameters for the function here
    @StartDate date = '2015-08-01',
    @EndDate date = '2015-08-31'
)
RETURNS int
AS
BEGIN
    -- Declare the return variable here
    DECLARE @BusDay int

    -- Add the T-SQL statements to compute the return value here
    SELECT @BusDay = Count(UPMCCALENDARM1.DATE) 
        from dbo.UPMCCALENDARM1
        where UPMC_BUSINESS_DAY = 't'
        and UPMCCALENDARM1.DATE between @StartDate and @EndDate

    -- Return the result of the function
    RETURN @BusDay

END
GO

在数据库中创建函数后,我将这两行添加到我的select语句中,它完美地运行。

--Custom function counts business days on UPMCCALENDARM1
, dbo.UPMCBusinessDayCount(DV_im_Audit_ASSIGNMENT.Time, Detail.RESOLVED_TIME) as BusDay

我可以将此函数用于包含此日期数据(或数据库上的任何查询)的任何范围。我可能会删除默认日期以及添加第三个参数来计算非工作日(UPMC_BUSINESS_DAY ='f')。但是因为问题已经解决了。