Sql 按类别查找缺失序列
我必须从下面的示例中识别丢失的记录Sql 按类别查找缺失序列,sql,sql-server,tsql,Sql,Sql Server,Tsql,我必须从下面的示例中识别丢失的记录 Category BatchNo TransactionNo +++++++++++++++++++++++++++++++++ CAT1 1 1 CAT1 1 2 CAT1 2 3 CAT1 2 4 CAT1 2 5 CAT1 3 6 CAT1 3 7 CAT1
Category BatchNo TransactionNo
+++++++++++++++++++++++++++++++++
CAT1 1 1
CAT1 1 2
CAT1 2 3
CAT1 2 4
CAT1 2 5
CAT1 3 6
CAT1 3 7
CAT1 3 8
CAT1 5 12
CAT1 5 13
CAT1 5 14
CAT1 5 15
CAT1 7 18
CAT2 1 1
CAT2 1 2
CAT2 3 6
CAT2 3 7
CAT2 3 8
CAT2 3 9
CAT2 4 10
CAT2 4 11
CAT2 4 12
CAT2 6 14
我需要一个脚本,将确定丢失的记录如下
Category BatchNo
+++++++++++++++++++
CAT1 4
CAT1 6
CAT2 2
CAT2 5
我不需要知道CAT1 8和CAT2 7不存在,因为它们可能还没有插入。这一个使用理货表。供参考:
样本数据
解决方案
最好创建一个投影表,并使用标准的左联接查找间隙:
declare @Sequencer table (
Id int primary key
);
insert into @Sequencer (Id)
select top (1000) row_number() over(order by (select null)) from master.dbo.spt_values;
select *
from @Sequencer s
inner join (
select Category, max(BatchNo) as [Size] from dbo.Table group by Category
) cat on cat.Size > s.Id
left join (
select distinct Category, BatchNo from dbo.Table
) t on t.Category = cat.Category and t.BatchNo = s.Id
where t.BatchNo is null;
当然,在现实生活中,您可能需要1000多行,因此请相应地进行调整。除了选择不可用的批次号之外,您还可以为每个类别创建临时结果集,其中包含所有可能的批次号,最大批次号
WITH Numbers AS (
SELECT MAX(BatchNo) AS Number
FROM #MyTable
UNION ALL
SELECT Number - 1
FROM Numbers
WHERE Number > 1
)
,CategorySizes AS (
SELECT Category
,MIN(BatchNo) AS StartBatch
,MAX(BatchNo) AS EndBatch
FROM #MyTable
GROUP BY Category
)
,PossibleBatches AS (
SELECT Category
,Numbers.Number AS BatchNo
FROM CategorySizes
CROSS JOIN Numbers
WHERE Numbers.Number BETWEEN CategorySizes.StartBatch AND CategorySizes.EndBatch
)
,MissingBatches AS (
SELECT PossibleBatches.Category
,PossibleBatches.BatchNo
FROM PossibleBatches
LEFT JOIN #MyTable
ON #MyTable.Category = PossibleBatches.Category
AND #MyTable.BatchNo = PossibleBatches.BatchNo
WHERE #MyTable.BatchNo IS NULL
)
SELECT *
FROM MissingBatches
create table TEMP(
Category varchar(10),
BatchNo int,
TransactionNo int
)
insert into TEMP values
('CAT1', 1, 1),
('CAT1', 1, 2),
('CAT1', 2, 3),
('CAT1', 2, 4),
('CAT1', 2, 5),
('CAT1', 3, 6),
('CAT1', 3, 7),
('CAT1', 3, 8),
('CAT1', 5, 9),
('CAT1', 7, 10),
('CAT2', 1, 1),
('CAT2', 1, 2),
('CAT2', 3, 3),
('CAT2', 4, 4),
('CAT2', 4, 5),
('CAT2', 4, 6),
('CAT2', 6, 7);
WITH BatchNo (BatchID,Category,MaxBatch) AS (
SELECT 1, Category, MAX(BatchNo) AS MaxBatch FROM TEMP GROUP BY Category
UNION ALL
SELECT BatchID + 1, Category, MaxBatch FROM BatchNo
WHERE BatchID < MaxBatch
)
SELECT
BatchNo.Category,
BatchNo.BatchID
FROM
BatchNo
WHERE
BatchID NOT IN (SELECT BatchNo FROM TEMP WHERE Category = BatchNo.Category)
ORDER BY
BatchNo.Category,
BatchNo.BatchID
DROP TABLE TEMP
如果不使用cycle或fetch,您可以使用这个:Category是表名的等价物。表演是完美的
DECLARE @t TABLE (RN INT IDENTITY,Category VARCHAR(255), BatchNo INT)
INSERT INTO @t
SELECT DISTINCT Category, BatchNo
FROM #Category
SELECT a.Category,a.BatchNo+1 AS BatchNo
FROM @t a
CROSS APPLY (SELECT * FROM @t b
WHERE a.RN+1 = b.RN AND
a.Category = b.Category AND
a.BatchNo+1 != b.BatchNo) x
批号不超过6?我们可以看到CAT1的批号为7@NeerajPrasadSharma@NeerajPrasad Sharma不,不是……那么最大批次数是否一直在变化?如果第2类批次号变为8,那么第1类批次号也应该变为第8批?@Neeraj Prasad Sharma不,这是我仅有的数据,不会改变
create table TEMP(
Category varchar(10),
BatchNo int,
TransactionNo int
)
insert into TEMP values
('CAT1', 1, 1),
('CAT1', 1, 2),
('CAT1', 2, 3),
('CAT1', 2, 4),
('CAT1', 2, 5),
('CAT1', 3, 6),
('CAT1', 3, 7),
('CAT1', 3, 8),
('CAT1', 5, 9),
('CAT1', 7, 10),
('CAT2', 1, 1),
('CAT2', 1, 2),
('CAT2', 3, 3),
('CAT2', 4, 4),
('CAT2', 4, 5),
('CAT2', 4, 6),
('CAT2', 6, 7);
WITH BatchNo (BatchID,Category,MaxBatch) AS (
SELECT 1, Category, MAX(BatchNo) AS MaxBatch FROM TEMP GROUP BY Category
UNION ALL
SELECT BatchID + 1, Category, MaxBatch FROM BatchNo
WHERE BatchID < MaxBatch
)
SELECT
BatchNo.Category,
BatchNo.BatchID
FROM
BatchNo
WHERE
BatchID NOT IN (SELECT BatchNo FROM TEMP WHERE Category = BatchNo.Category)
ORDER BY
BatchNo.Category,
BatchNo.BatchID
DROP TABLE TEMP
DECLARE @t TABLE (RN INT IDENTITY,Category VARCHAR(255), BatchNo INT)
INSERT INTO @t
SELECT DISTINCT Category, BatchNo
FROM #Category
SELECT a.Category,a.BatchNo+1 AS BatchNo
FROM @t a
CROSS APPLY (SELECT * FROM @t b
WHERE a.RN+1 = b.RN AND
a.Category = b.Category AND
a.BatchNo+1 != b.BatchNo) x
create table #cat(
Category varchar(10),
BatchNo int,
TransactionNo int
)
insert into #cat values
('CAT1', 1, 1),
('CAT1', 1, 2),
('CAT1', 2, 3),
('CAT1', 2, 4),
('CAT1', 2, 5),
('CAT1', 3, 6),
('CAT1', 3, 7),
('CAT1', 3, 8),
('CAT1', 5, 9),
('CAT1', 7, 10),
('CAT2', 1, 1),
('CAT2', 1, 2),
('CAT2', 3, 3),
('CAT2', 4, 4),
('CAT2', 4, 5),
('CAT2', 4, 6),
('CAT2', 6, 7);
SELECT DISTINCT C.Category, C.BatchNo + 1
FROM #cat c
OUTER APPLY
(
SELECT *
FROM #cat c1
WHERE C1.BatchNo = C.BatchNo + 1 AND C1.Category = C.Category
) C2
WHERE C2.BatchNo IS NULL
AND
C.BatchNo <> (SELECT MAX(BatchNo) FROM #cat C3 WHERE c3.Category = c.Category)