Sql 无法完成查询(运行时间太长)

Sql 无法完成查询(运行时间太长),sql,sql-server,Sql,Sql Server,我试图得到一些测试结果的总体通过率 序列号代表一种仪器。一台仪器要通过107项不同的测试。试验分为两部分: Linux测试(21) 其他(共86个,如电压测试、灯光测试) 在两种情况下,仪器将被视为通行证 标准方式:它在一次运行中通过107个不同的测试。代码如下: 选择序列号 从桌子上 按序号、条目分组 有计数(不同的测试标准)>=107 另一种方法:它在一次运行中通过107个不同的测试,或者 它在一轮中通过了86项其他测试,在一轮中通过了21项Linux测试 晚些时候 表中的“overallt

我试图得到一些测试结果的总体通过率

序列号代表一种仪器。一台仪器要通过107项不同的测试。试验分为两部分:

  • Linux测试(21)
  • 其他(共86个,如电压测试、灯光测试)
  • 在两种情况下,仪器将被视为通行证

  • 标准方式:它在一次运行中通过107个不同的测试。代码如下:

    选择序列号 从桌子上 按序号、条目分组 有计数(不同的测试标准)>=107

  • 另一种方法:它在一次运行中通过107个不同的测试,或者 它在一轮中通过了86项其他测试,在一轮中通过了21项Linux测试 晚些时候

    表中的“overalltestrunstatus”列仅表示仪器通过了列表中的所有测试,但列表本身可能不完整。(假设一个仪器获得“overalltestrunstatus”,但它通过的测试<107,它仍然是失败的)。有时,如果仪器失败或通过测试的次数少于某个数字,则仪器将重新运行。所以“entry”代表该乐器所代表的回合

  • 我的目标是,找到那些通过测试但不符合标准的仪器

    我的想法是找到所有那些“总体测试运行状态”等于通过但通过测试少于107的仪器。然后遍历结果和仪器的每个条目。如果它通过了86个其他测试,我会给它一个检查,如果通过了其他21个Linux,我会给它另一个检查。稍后我将计算所有有两张支票的仪器

    我想要的是:

    +----------------+------------+---------------+------------+
    |  serial number |   entries  | others tests  | Linux tests|
    +----------------+------------+---------------+------------+
    |  170119904     |     1      |       yes     |    no      |
    +----------------+------------+---------------+------------+
    |  170119904     |     2      |       no      |    yes     |
    +----------------+------------+---------------+------------+
    |  180117000     |     1      |       no      |    no      |
    +----------------+------------+---------------+------------+
    |  180117000     |     2      |       no      |    no      |
    +----------------+------------+---------------+------------+
    
    因此,通过检查特定序列号是否通过了其他测试和Linux测试。我会知道它通过与否

    我的问题是,每次查询运行大约20个小时,然后给出一个错误,如“断开连接”或“出现一些内部错误”。我永远也无法真正地度过难关。有什么想法吗?我真的很感谢你的帮助

    这是表格:

    +----------------------+--------------+----------+----------------+------------+---------+
    | overalltestrunstatus | serialnumber | passfail |  testcriteria  |  testname  | Entries |
    +----------------------+--------------+----------+----------------+------------+---------+
    | PASS                 |    170119904 | Pass     | Backlight test | Functional |       1 |
    +----------------------+--------------+----------+----------------+------------+---------++----------------------+--------------+----------+----------------+------------+---------+
    | PASS                 |    170119904 | Pass     | Linux set test | Functional |       1 |
    +----------------------+--------------+----------+----------------+------------+---------++----------------------+--------------+----------+----------------+------------+---------+
    | PASS                 |    170119904 | Pass     | Factor    test | Functional |       1 |
    +----------------------+--------------+----------+----------------+------------+---------++----------------------+--------------+----------+----------------+------------+---------+
    | PASS                 |    170119904 | Pass     | Voltage   test | Functional |       1 |
    +----------------------+--------------+----------+----------------+------------+---------++----------------------+--------------+----------+----------------+------------+---------+
    | PASS                 |    170119904 | Pass     | Digital   test | Functional |       1 |
    +----------------------+--------------+----------+----------------+------------+---------++----------------------+--------------+----------+----------------+------------+---------+
    | PASS                 |    170119904 | Pass     | Detactor  test | Functional |       1 |
    +----------------------+--------------+----------+----------------+------------+---------+
    
    这是我的代码:

    /* -serialnumber |-- entries--|--Pass1 --|--Pass2---|
       --------------|------------|----------|----------|
    */
    DECLARE @checklist TABLE
    (
      serialnumber varchar(100), 
      entries int,
      passother int default  0,
      passlinux int default  0
    )
    
    DECLARE @temp TABLE
    (
      serialnumber int, 
      entries int,
      passother int default  0,
      passlinux int default  0
    )
    
    -- select serial number into the table
    
    -- PCBA 214 ge to be counted
    INSERT INTO @checklist (serialnumber, entries)
        SELECT serialnumber, entries 
        FROM dbo.boardtestresults1_full_view  t2
        WHERE partnumber = 'PCBA-10214-0001' 
            AND t2.serialnumber IN 
            (SELECT DISTINCT serialnumber
            FROM dbo.boardtestresults1_full_view  
            WHERE partnumber = 'PCBA-10214-0001' AND overalltestrunstatus = 'Pass' AND serialnumber NOT IN (
            SELECT DISTINCT serialnumber
            FROM dbo.boardtestresults1_full_view  
            WHERE partnumber = 'PCBA-10214-0001' AND overalltestrunstatus = 'Pass'
            GROUP BY serialnumber, Entries 
            HAVING COUNT(DISTINCT combined) >= 107))
    
    
    
    -- check all for PCBA 10214
    
    DECLARE @MyCursor1 CURSOR;
    DECLARE @snumber VARCHAR(100); -- serailnumber
    DECLARE @entries VARCHAR(100); -- entries
    DECLARE @others int;
    DECLARE @linux int;
    DECLARE @pass1 int;
    DECLARE @pass2 int;
    
    BEGIN
        -- get serial numbers for all PCBA 214 from checklist
        SET @MyCursor1 = CURSOR FOR
        SELECT serialnumber, Entries
        FROM @checklist
        WHERE serialnumber like 'PCBA-10214-0001%' 
    
        -- get the roll
        OPEN @MyCursor1 
        FETCH NEXT FROM @MyCursor1 
        INTO @snumber, @entries
    
        -- loop through
        WHILE @@FETCH_STATUS = 0
        BEGIN
          /*
             YOUR ALGORITHM GOES HERE   
          */
        -- if pass the most or if pass linux
        IF ((SELECT COUNT(DISTINCT combined)FROM dbo.boardtestresults1_full_view WHERE  serialnumber = @snumber AND entries = @entries) >= 86)
            UPDATE @checklist SET passother = 1 WHERE serialnumber = @snumber AND entries = @entries
        ELSE IF ((SELECT COUNT(DISTINCT combined)FROM dbo.boardtestresults1_full_view WHERE  serialnumber = @snumber AND entries = @entries AND testname = 'LINUX Test' AND overalltestrunstatus = 'Pass') >= 21) 
            UPDATE @checklist SET passlinux = 1 WHERE serialnumber = @snumber AND entries = @entries
        END; 
    
        CLOSE @MyCursor1 ; 
        DEALLOCATE @MyCursor1;
    END;
    

    下面是一个工作示例,
    PassFail
    列未被计算,但在那里它对查询没有限制。为了简化示例,我添加了一个名为
    TestType
    的专栏,在您的用例中不太清楚Linux测试是如何从示例集派生出来的,可能是TestCriteria,但这使它不那么模棱两可。您应该能够获得测试的二进制文件,如果您需要进一步的帮助,您需要定义所有数据,我们可以提供帮助

    declare @example as table (
        ExampleID     int identity(1,1) not null primary key clustered
    ,   OverAllStatus nvarchar(255) not null
    ,   SN            int not null
    ,   PassFail      nvarchar(255) not null
    ,   TestType      bit not null
    ,   TestCriteria  nvarchar(255) not null
    ,   Entry_        int not null
    );
    
    insert into @example (OverAllStatus, SN, PassFail, TestType, TestCriteria, Entry_)
    select 'PASS', 170119904, 'Pass', 0, 'Backlight test', 1 union all
    select 'PASS', 170119904, 'Pass', 0, 'Factor test', 1 union all
    select 'PASS', 170119904, 'Pass', 0, 'Voltage test', 1 union all
    select 'PASS', 170119904, 'Pass', 0, 'Detactor test', 1 union all
    
    select 'PASS', 170119904, 'Pass', 0, 'Backlight test', 2 union all
    select 'PASS', 170119904, 'Pass', 1, 'Linux set test', 2 union all
    select 'PASS', 170119904, 'Pass', 0, 'Factor test', 2 union all
    select 'PASS', 170119904, 'Pass', 0, 'Voltage test', 2 union all
    select 'PASS', 170119904, 'Fail', 0, 'Digital test', 2 union all
    select 'PASS', 170119904, 'Pass', 0, 'Detactor test', 2 union all
    
    select 'PASS', 180117000, 'Pass', 0, 'Backlight test', 1 union all
    select 'PASS', 180117000, 'Pass', 1, 'Linux set test', 1 union all
    select 'PASS', 180117000, 'Pass', 0, 'Factor test', 1 union all
    select 'PASS', 180117000, 'Pass', 0, 'Digital test', 2 union all
    select 'PASS', 180117000, 'Pass', 0, 'Detactor test', 1;
    
    
      --| Control Group, only those that pass but does not have 107 records (OverAllStatus)
      ;with cte as (
         select SN
              , Entry_
              , count(*) cnt
           from @example
          where OverAllStatus = 'Pass'
       group by SN, Entry_
       --| Control count - this is your 107 or the numbers of tests the SN has passed
         having count(*) < 7
                )
       --| We are setting the count of records to the Test Type or the grouping
        , cte2 as (
        select b.SN
             , a.Entry_
             , iif(TestType = 1, 'Linux', 'Other') Test
          from cte a
          join @example b
            on a.SN = b.SN
           and a.Entry_ = b.Entry_
                )
        --| Roll up the counts
        , cte3 as ( 
        select distinct a.SN
             , a.Entry_
             , count(*) over(partition by a.SN, a.Test, a.Entry_) cnt
             , a.Test
          from cte2 a
                )
    
      --| Pivot the result set
        select SN
             , Entry_
             , [Other]
             , [Linux]
          from (
                    select SN
                         , Entry_
                         , cnt
                         , test
                      from cte3
                      ) as x
                pivot 
                    (
                     max(cnt)
                     for Test in ([Other], [Linux])
                    ) as p;
    

    你能编辑你的问题并提供一些(简化的)样本数据和期望的结果吗?你也能在没有所有差异的情况下尝试吗?
    光标
    可能对问题没有帮助。看起来可以用数据集方法编写。while循环中没有fetch next。看起来像是一个无限循环问题。循环所能做的就是减慢一个本来很快的过程。在你的情况下,无限期。这应该是一个基于集合的update语句,带有大小写表达式。非常感谢。我是SQL新手,这可能需要一段时间才能理解和应用。无论如何,我真的很感谢你的帮助。np,一旦你评估了它,如果它对你有帮助,请选择它作为答案。如果您对代码或如何进行更改有任何疑问,请发布,如果我没有回复,我相信会有人回复;我会努力跟进的,我很乐意,但我不能,因为我的声誉低于15。
    SN          Entry_  Other   Linux
    170119904   1       4       NULL
    180117000   1       3       1
    170119904   2       5       1
    180117000   2       1       NULL