SQL Server View 让我很困惑 - 有子查询并使用假期表

问题描述 投票:0回答:1

我继承了一个我不理解的复杂的(对我而言)SQL Server 视图。对于查询中发生的情况,我希望得到一些建议。我还想将查询分解为单独的查询,以便我可以更好地了解发生了什么。

查询正在查找测试结果的 DueDate(计算得出)小于当前日期的记录,这意味着测试结果已过期。

它还会查看假期表以排除某些日子,以及排除周六和周日。我想。

嵌套的 select 语句真的让我很困惑。

查询非常慢,这就是为什么我需要理解然后改进或替换它。

环境是 SQL Server 数据库后端、Microsoft Access 前端。 Access 使用链接的 SQL Server 视图作为报表对象的记录源。

提前致谢!


select t.OrderID, t.SampleNumber, t.Matrix, t.CustomerSampleNumber, t.TestGroup, t.[Priority], t.CustomerID, t.CustomerContact, t.SignOffDate, t.SignOff, t.[Text], 
t.Method, t.OrderDetails_User2, t.Commnt, t.OrderDueDate, t.ReportedDate, t.DueDateFlag, t.ReceiveDate, t.TAT, t.Test, t.[Param], t.ResultStatus, t.CustomerName, t.CountOfSampleNumber, t.expDueDate
from    (
            select t1.OrderID, t1.SampleNumber, t1.Matrix, t1.CustomerSampleNumber, t1.TestGroup, t1.[Priority], t1.CustomerID, t1.CustomerContact, 
            t1.SignOffDate, t1.SignOff, t1.[Text], t1.Method, t1.OrderDetails_User2, t1.Commnt, t1.OrderDueDate, t1.ReportedDate, t1.DueDateFlag, 
            t1.ReceiveDate, t1.TAT, t1.Test, t1.[Param], t1.ResultStatus, t1.CustomerName, t1.CountOfSampleNumber, t1.expDueDate, 
            rnb = row_number() over (partition by t1.OrderID, t1.SampleNumber, t1.Matrix, t1.CustomerSampleNumber, t1.TestGroup, 
            t1.[Priority], t1.CustomerID, t1.CustomerContact, t1.SignOffDate, t1.SignOff, t1.[Text], t1.Method, t1.OrderDetails_User2, 
            t1.Commnt, t1.OrderDueDate, t1.ReportedDate, t1.DueDateFlag, t1.ReceiveDate, t1.TAT, t1.Test, t1.[Param], t1.ResultStatus, 
            t1.CustomerName, t1.CountOfSampleNumber order by t1.expDueDate)
            from            (
                                select  *, 
                                        expDueDate  = cast(dateadd(day, t1.TAT + t2.num, t1.ReceiveDate) as date)
                                from    (
                                            select distinct
                                                OrderID                 = o.OrderID, 
                                                SampleNumber            = od.SampleNumber, 
                                                Matrix                  = od.Matrix, 
                                                CustomerSampleNumber    = od.CustomerSampleNumber, 
                                                TestGroup               = sd.TestGroup, 
                                                [Priority]              = o.[Priority], 
                                                CustomerID              = o.CustomerID, 
                                                CustomerContact         = o.CustomerContact, 
                                                SignOffDate             = o.SignOffDate, 
                                                SignOff                 = o.SignOff, 
                                                [Text]                  = p.[Text], 
                                                Method                  = sd.Method, 
                                                OrderDetails_User2      = od.OrderDetails_User2, 
                                                Commnt                  = o.Commnt, 
                                                OrderDueDate            = o.OrderDueDate, 
                                                ReportedDate            = o.ReportedDate, 
                                                DueDateFlag             = sd.DueDateFlag, 
                                                ReceiveDate             = od.ReceiveDate, 
                                                TAT                     = p.TAT, 
                                                Test                    = r.Test,
                                                [Param]                 = r.[Param], 
                                                ResultStatus            = r.ResultStatus, 
                                                CustomerName            = c.CustomerName, 
                                                CountOfSampleNumber     = qpsn.CountOfSampleNumber
                                            from            SMSU.Orders                         o
                                                inner join  SMSU.OrderDetails                   od      on od.OrderID = o.OrderID
                                                inner join  SMSU.SampleDetails                  sd      on sd.SampleNumber = od.SampleNumber
                                                inner join  SMSU.Priorities                     p       on p.[Priority] = o.[Priority]
                                                inner join  SMSU.Results                        r       on r.Test = sd.Test and r.SampleNumber = sd.SampleNumber and r.ORderId = sd.OrderId
                                                inner join  SMSU.Customers                      c       on c.CustomerID = o.CustomerID
                                                inner join  dbo.GC_qryParametersStillNeeded_01  qpsn    on qpsn.OrderID = o.OrderID
                                            WHERE r.ResultStatus = 0

                                    )   t1
                                    cross join  (
                                                    select top 50  -- <-- limit of days was 730
                                                        num = row_number() over (order by (select NULL)) - 1
                                                    from Information_Schema.columns
                                                )   t2
                            )                   t1
                left join   dbo.GC_tblHolidays  o   on o.HolidayDate between t1.ReceiveDate and dateadd(day, t1.TAT + t1.num, t1.ReceiveDate) and DATENAME(dw, o.HolidayDate) not in ('Saturday','Sunday') 
            group by t1.OrderID, t1.SampleNumber, t1.Matrix, t1.CustomerSampleNumber, t1.TestGroup, t1.[Priority], t1.CustomerID, t1.CustomerContact, t1.SignOffDate, t1.SignOff, t1.[Text], t1.Method, t1.OrderDetails_User2, t1.Commnt, t1.OrderDueDate, t1.ReportedDate, t1.DueDateFlag, t1.ReceiveDate, t1.TAT, t1.Test, t1.[Param], t1.ResultStatus, t1.CustomerName, t1.CountOfSampleNumber, t1.expDueDate    
            having DATEDIFF(dd, ReceiveDate, expDueDate) - (DATEDIFF(wk, ReceiveDate, expDueDate) * 2) - (CASE WHEN DATENAME(dw, ReceiveDate) = 'Sunday' THEN 1 ELSE 0 END) - (CASE WHEN DATENAME(dw, expDueDate) = 'Saturday' THEN 1 ELSE 0 END) - COUNT(o.HolidayDate) = t1.TAT AND CAST(t1.expDueDate as date) < GETDATE()
            )   t
where t.rnb = 1


这是示例输出。

OrderID SampleNumber 矩阵 CustomerSampleNumber TestGroup 优先级 CustomerID CustomerContact SignOffDate SignOff 文本方法 OrderDetails_User2 Commnt OrderDueDate ReportedDate DueDateFlag ReceiveDate TAT 测试参数 ResultStatus CustomerName CountOfSampleNumber expDueDate 123456 123456-02 水管第二左 NULL 0 1234567 John Do 50:52.8 1 正常 SM 2110 NULL NULL NULL NULL 0 00:00.0 10 ZZ 外观样本描述 0 Outisde Park 12 9/24/2024 123456 123456-02 水管 左第二 标准金属分析 0 1234567 John Do 50:52.8 1 正常 EPA 200.7 NULL NULL NULL NULL 0 00:00.0 10 11-铝 ICP 铝业,Al 0 Outisde Park 12 9/24/2024 123456 123456-02 水管道 第二左 标准金属分析 0 1234567 John Do 50:52.8 1 正常 EPA 200.7 NULL NULL NULL NULL 0 00:00.0 10 20-铜 by ICP Copper, Cu 0 Outisde Park 12 9/24/2024 123456 123456-02 水管道第二左标准金属分析 0 1234567 John Do 50:52.8 1 正常 EPA 200.7 NULL NULL NULL NULL 0 00:00.0 10 21-Iron by ICP Iron, Fe 0 Outisde Park 12 9/24/2024

sql-server row-number information-schema
1个回答
0
投票

出于分析目的,消除所有枚举列有助于减少混乱并使查询更易于管理。经过一些清理和重新格式化后的结果(不再有效的 SQL)将类似于:

select
    t.*many*
from (
    select
        t1.*many*
        rnb = row_number() over (partition by t1.*many* order by t1.expDueDate)
    from (
        select
            *many*, 
            expDueDate = cast(dateadd(day, t1.TAT + t2.num, t1.ReceiveDate) as date)
        from (
            select distinct
                o.*many*,
                od.*many*,
                sd.*many*,
                p.*many*,
                r.*many*,
                c.*many*,
                qpsn.CountOfSampleNumber
            from SMSU.Orders              o
            inner join SMSU.OrderDetails  od on od.OrderID = o.OrderID
            inner join SMSU.SampleDetails sd on sd.SampleNumber = od.SampleNumber
            inner join SMSU.Priorities    p  on p.[Priority] = o.[Priority]
            inner join SMSU.Results       r  on r.Test = sd.Test and r.SampleNumber = sd.SampleNumber and r.ORderId = sd.OrderId
            inner join SMSU.Customers     c  on c.CustomerID = o.CustomerID
            inner join dbo.GC_qryParametersStillNeeded_01 qpsn on qpsn.OrderID = o.OrderID
            WHERE r.ResultStatus = 0
        ) t1
        cross join (
            select top 50 -- <-- limit of days was 730
                num = row_number() over (order by (select NULL)) - 1
            from Information_Schema.columns
        ) t2
    ) t1
    left join dbo.GC_tblHolidays o
        on o.HolidayDate between t1.ReceiveDate and dateadd(day, t1.TAT + t1.num, t1.ReceiveDate)
        and DATENAME(dw, o.HolidayDate) not in ('Saturday','Sunday') 
    group by t1.*many*
    having DATEDIFF(dd, ReceiveDate, expDueDate)
               - (DATEDIFF(wk, ReceiveDate, expDueDate) * 2)
               - (CASE WHEN DATENAME(dw, ReceiveDate) = 'Sunday' THEN 1 ELSE 0 END)
               - (CASE WHEN DATENAME(dw, expDueDate) = 'Saturday' THEN 1 ELSE 0 END)
               - COUNT(o.HolidayDate)
           = t1.TAT
    AND CAST(t1.expDueDate as date) < GETDATE()
) t
where t.rnb = 1

据我所见:

  1. 最里面的查询是从一组连接表中进行的典型选择。我的猜测是,这会为每个样本细节生成一行。
  2. 下一级交叉连接与数字序列生成器
    1..50
    或(是
    1..730
    ),并根据内部查询结果和序列号的每个组合计算
    expDueDate
    。我的猜测是,我们正在寻找一个特定的“到期”日期,但不知道如何直接计算它。相反,我们正在生成一系列日期,以最终找到符合我们的截止日期标准的日期。
  3. 下一个级别使用连接与假期表和分组的组合来计算给定日期范围内的假期数。它还计算经过的工作日(总经过的天数减去周末和假期)并过滤结果经过的工作日
    = t1.TAT
    。 (我猜是结果被视为逾期之前的工作日数)。
  4. 对于步骤 2 中生成的所有序列号,步骤 3 应消除除一个或几个之外的所有序列号。
  5. 为了将其减少到每个样本细节最多一个,
    rnb = row_number() over (...)
    where t.rnb = 1
    的组合将为每个样本细节选择最早的合格
    expDueDate

我相信这一切都是为了根据已过的工作日来识别过期的样本详细信息。

我的总体印象是,这是可怕的(并且可能效率低下)代码(可能会起作用),但是必须有更好的方法,可能使用几个交叉应用和更有效地使用日历表。

© www.soinside.com 2019 - 2024. All rights reserved.