排序表

时间:2019-05-15 15:59:15

标签: sql

我有一个表(序列),该表确定操作的顺序,并且基于此表,我们必须从摘要表(摘要)中提取相应的操作,并显示其余属性。

序列

PART    OP1 OP2 OP3 OP4 OP5 OP6 OP7 OP8 
ABC      2   3   4   5   1   0   0   0

摘要

Part    Serail  OP  Status        Date Accomplished
ABC     2196    1   OPEN          18-Jul-14
ABC     2196    2   PREV ACCO     21-Jan-11
ABC     2196    3   PREV ACCO     21-Jan-11
ABC     2196    4   PREV ACCO     21-Jan-11
ABC     2196    5   COMPLETE      19-Jan-11
ABC     5596    1   COMPLETE      30-Jun-16
ABC     5596    5   COMPLETE      30-Jun-16
ABC     5845    1   COMPLETE      25-Nov-17
ABC     5845    2   PREV ACCO     27-Aug-09
ABC     5845    5   PREV ACCO     27-Aug-09
ABC     6076    1   OPEN          18-Jul-14
ABC     6076    2   PREV ACCO     2-Apr-12
ABC     6076    5   COMPLETE      29-Mar-12
ABC     6076    10  DELETED       10-MAR-19 
  1. 获取OP1的值,并查看其所有相关联的内容,并显示相应的状态和完成日期。如果不存在特定序列号,则显示N / A
    示例-Serial 5596在摘要中仅具有操作1和5,但在序列表中该部件具有操作1,2,3,4,5。因此,前3个操作将为N / A

  2. 如果仅在摘要中存在但在序列表中不存在的操作,则将其显示在与其关联的序列的底部。例如-Serial 6076的操作10的状态为“已删除”,仅存在于摘要中,但不存在于序列表中,在这种情况下,在处理了序列表中的所有内容后,我们将其显示为操作6的结尾。

我的结果应该如下

Part    Serial  OP  Status          Date
ABC     2196    1   PREV ACCO   21-Jan-11
ABC     2196    2   PREV ACCO   21-Jan-11
ABC     2196    3   PREV ACCO   21-Jan-11
ABC     2196    4   COMPLETE    19-Jan-11
ABC     2196    5   OPEN        18-Jul-14

ABC     5596    1   N/A         N/A
ABC     5596    2   N/A         N/A
ABC     5596    3   N/A         N/A
ABC     5596    4   COMPLETE    30-Jun-16
ABC     5596    5   COMPLETE    30-Jun-16

ABC     5845    1   PREV ACCO   27-Aug-09
ABC     5845    2   N/A         N/A
ABC     5845    3   N/A         N/A
ABC     5845    4   PREV ACCO   27-Aug-09
ABC     5845    5   COMPLETE    25-Nov-17

ABC     6076    1   PREV ACC    2-Apr-12
ABC     6076    2   N/A         N/A
ABC     6076    3   N/A         N/A
ABC     6076    4   COMPLETE    29-Mar-12
ABC     6076    5   OPEN        18-Jul-14
ABC     6076    6   DELETED     10-MAR-19 

1 个答案:

答案 0 :(得分:0)

这需要您有一个数字表-有关创建该表的选项,请参见What is the best way to create and populate a numbers table?

也许有更优雅的解决方案,但这是您的选择:

set transaction isolation level read uncommitted;

declare @Summary as table
(
    [Part] nvarchar(3),
    [Serial] int,
    [OP] smallint,
    [Status] nvarchar(30),
    [DateAccomplished] date
);
insert into @Summary
(
    [Part],
    [Serial],
    [OP],
    [Status],
    [DateAccomplished]
)
values
('ABC', 2196, 1, 'OPEN', '18-Jul-14'),
('ABC', 2196, 2, 'PREV ACCO', '21-Jan-11'),
('ABC', 2196, 3, 'PREV ACCO', '21-Jan-11'),
('ABC', 2196, 4, 'PREV ACCO', '21-Jan-11'),
('ABC', 2196, 5, 'COMPLETE', '19-Jan-11'),
('ABC', 5596, 1, 'COMPLETE', '30-Jun-16'),
('ABC', 5596, 5, 'COMPLETE', '30-Jun-16'),
('ABC', 5845, 1, 'COMPLETE', ' 25-Nov-17'),
('ABC', 5845, 2, 'PREV ACCO', '27-Aug-09'),
('ABC', 5845, 5, 'PREV ACCO', '27-Aug-09'),
('ABC', 6076, 1, 'OPEN', '18-Jul-14'),
('ABC', 6076, 2, 'PREV ACCO', '2-Apr-12'),
('ABC', 6076, 5, 'COMPLETE', '29-Mar-12'),
('ABC', 6076, 10, 'DELETED', '10-MAR-19 ');

with [InitialRows] as
(
    select
        s.Part,
        s.Serial,
        n.Number as [OP]
    from @Summary as [s]
        cross apply
        (
            select 
                n.Number
            from dbo.Numbers as [n]
            where n.Number between 1 and 6
        ) as [n]
    group by
        s.Part,
        s.Serial,
        n.Number
    having n.Number <= max(s.OP)
)
select 
    ir.Part,
    ir.Serial,
    ir.OP,
    coalesce(s.[Status], sMax.[Status], 'N/A') as [Status],
    coalesce(cast(s.DateAccomplished as nvarchar(10)), cast(sMax.DateAccomplished as nvarchar(10)), 'N/A') as [DateAccomplished]
from [InitialRows] as [ir]
    left join @Summary as [s] on s.Part = ir.Part
        and s.Serial = ir.Serial
        and s.OP = ir.OP
    left join
    (
        select
            s.Part,
            s.Serial,
            iif(max(s.OP) > 5, 6, max(s.OP)) as [OP],
            s.[Status],
            s.[DateAccomplished]
        from @Summary as [s]
        group by
            s.Part,
            s.Serial,
            s.[Status],
            s.[DateAccomplished]
    ) as [sMax] on sMax.Part = ir.Part
        and sMax.Serial = ir.Serial
        and sMax.OP = ir.OP
order by
    ir.Part,
    ir.Serial,
    ir.OP