Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server MSSQL组,直到类型更改_Sql Server - Fatal编程技术网

Sql server MSSQL组,直到类型更改

Sql server MSSQL组,直到类型更改,sql-server,Sql Server,我目前有以下表格: ╔════╦══════════╦════════════╗ ║ ID ║ PartType ║ PartStatus ║ ╠════╬══════════╬════════════╣ ║ 1 ║ A ║ OK ║ ║ 2 ║ A ║ BAD ║ ║ 3 ║ A ║ OK ║ ║ 4 ║ A ║ OK ║ ║ 5 ║ B ║ OK

我目前有以下表格:

╔════╦══════════╦════════════╗
║ ID ║ PartType ║ PartStatus ║
╠════╬══════════╬════════════╣
║  1 ║ A        ║ OK         ║
║  2 ║ A        ║ BAD        ║
║  3 ║ A        ║ OK         ║
║  4 ║ A        ║ OK         ║
║  5 ║ B        ║ OK         ║
║  6 ║ B        ║ BAD        ║
║  7 ║ A        ║ OK         ║
╚════╩══════════╩════════════╝
我希望能够按零件类型对它们进行分组,直到零件类型发生变化。所以它的输出应该是这样的:

╔══════════╦══════════╗
║ PartType ║ Quantity ║
╠══════════╬══════════╣
║ A        ║        4 ║
║ B        ║        2 ║
║ A        ║        1 ║
╚══════════╩══════════╝

使用您的示例输入考虑此测试表:

DECLARE @test TABLE
(
    ID int IDENTITY(1,1) NOT NULL,
    PartType nvarchar(1) NOT NULL,
    PartStatus nvarchar(50) NOT NULL
)

INSERT INTO @test (PartType,PartStatus)
VALUES 
(N'A',N'OK'),
(N'A',N'BAD'),
(N'A',N'OK'),
(N'A',N'OK'),
(N'B',N'OK'),
(N'B',N'BAD'),
(N'A',N'OK');
当PartType更改时,我使用应用程序获取下一个ID:

SELECT t.PartType
, COUNT(t.ID) AS Quantity
FROM @test t
INNER JOIN (
    SELECT MAX(ID) + 1 axID
    FROM @test
) m 
ON 1 = 1
OUTER APPLY (
    SELECT TOP 1 s.ID as extID
    FROM @test s
    WHERE s.ID > t.ID
    AND s.PartType <> t.PartType
    ORDER BY s.ID ASC
) n 
GROUP BY t.PartType, ISNULL(n.extID,m.axID)
ORDER BY ISNULL(n.extID,m.axID)

您还可以使用row_number进行此类分组,这对于更大的数据集应该会更好,因为您不必进行任何连接。这还应返回预期结果:

select PartType, count(*)
from (
  select *, 
    row_number() over (order by ID) as RN1, 
    row_number() over (partition by PartType order by ID) as RN2
  from yourtable
) X
group by PartType, RN1 - RN2
order by min(ID)

这里的诀窍是,第一个行号对所有行进行编号,第二个行号按PartType对它们进行分区。因此,当RN1和RN2之间的差异发生变化时,它是一种不同的类型。

尝试使用递归CTE编写这个简单的脚本

WITH cte_test as(
    select *,1 as recno from @Table1 where id=1
    union all
    select t.*,(case when c.PartType = t.PartType then recno else recno+1 end ) 
    from @Table1 t inner join cte_test c on t.ID =  c.ID+1
)
select PartType,count(*) from cte_test 
group by recno,PartType
order by recno
option (maxrecursion 0)

如果您使用的是SQL Server 2012或更高版本,那么另一个值得一提的方法是使用2012年提供的窗口功能

您可以使用LAG函数检测数据集中何时发生状态更改,并且可以使用SUM OVER子句为数据生成分组id。下面的示例演示了如何做到这一点

    DECLARE @parts TABLE
    (
        ID int IDENTITY(1,1) NOT NULL PRIMARY KEY,
        PartType nvarchar(1) NOT NULL,
        PartStatus nvarchar(50) NOT NULL
    )

    INSERT INTO @parts (PartType,PartStatus)
    VALUES 
    (N'A',N'OK'),
    (N'A',N'BAD'),
    (N'A',N'OK'),
    (N'A',N'OK'),
    (N'B',N'OK'),
    (N'B',N'BAD'),
    (N'A',N'OK');


    WITH CTE_PartTypeWithStateChange
    AS
    (
        SELECT   ID
                ,PartType
                ,PartStatus
                ,(
                    CASE
                        WHEN (LAG(PartType, 1, '') OVER (ORDER BY ID) <> PartType) THEN  1
                        ELSE 0
                    END
                    ) HasStateChanged
        FROM  @parts 
    )
    ,
    CTE_PartTypeWithGroupID
    AS
    (
        SELECT   ID
                ,PartType
                ,PartStatus
                ,SUM(HasStateChanged) OVER (ORDER BY ID ROWS UNBOUNDED PRECEDING) AS GroupID
        FROM    CTE_PartTypeWithStateChange
    )
    SELECT   MAX(PartType) AS PartType
            ,COUNT(PartType) AS Quantity
    FROM     CTE_PartTypeWithGroupID
    GROUP BY GroupID

虽然代码要多一些,但这种方法确实可以减少源表上的读取次数,因为您没有执行任何自联接。这种方法还减少了查询必须执行的排序数量,这将提高大型数据集的性能

您使用的是什么版本的SQL Server?在提出问题之前您尝试了什么?SQL是基于集合的,除非您引入一个顺序,否则它不知道要到什么时候。您想订购什么-ID?我几乎想问为什么,因为你似乎是在以一种没有意义的方式组织数据。原因是因为我们有一条生产线,我们需要知道他在变更前生产了多少件,以便与我们的计划交叉核对,并在变更前验证他们是否达到了目标。好的,这意味着ID应该是一个时间戳,但是如果没有明确的字段,如果按顺序插入行,您确实可以使用ID作为近似值。就在几天前,我用自己的方式解决了类似的问题……是的,我误解了这个问题,我的错。我只是觉得他想为他的团队下订单。我将编辑答案,当前的答案不符合要求。效果非常好。非常感谢。聪明的事情不是它检测分区开关,而是RN1-RN2组实际上可以工作,不管分区是如何排列的。非常感谢。因为我的表有很多记录,所以每次请求都可以节省一些时间。