2011-11-22 48 views
1

我需要識別序號爲數字的缺失產品。換句話說,我們每個商店都有一組產品銷售,每個產品都有唯一的編號。最終用戶需要一份報告來確定日期範圍內缺失的小部件。如何在SQL Server 2008 R2中不使用光標填充表格

Store Product Number 
Store 1 Widget 100 
Store 1 Widget 101 
Store 1 Widget 102 
Store 1 Widget 104 
Store 2 Widget 201 
Store 2 Widget 202 
Store 2 Widget 203 

我認爲這樣做是爲了獲得MAX(數)和MIN(號碼),然後填充表變量的所有序列中數字的最好方式。如果產品表中不存在來自表變量的Widget編號,我會返回該編號並將其標記爲缺失。

但是;我們的DBA非常反對遊標,我知道WHILE循環需要很多開銷。另外,我不確定如何以逐店方式做到這一點。

有沒有人知道如何以基於集合的方式做到這一點?

小部件本身有數字,所以當您銷售小部件#1時,您銷售的下一個小部件應該是小部件#2。然而;有時候,這種情況不會發生,並且會出售小部件#3 - 小部件#2丟失,並且不在數據庫中。我需要在報告中確定小部件#1和#3已售出而#2丟失。

+3

你有一個DBA誰也無法用一組基礎的解決方案幫助嗎?解僱DBA! – JonH

+0

上週我被告知,我們的DBA太忙了,無法回答問題,我需要建立在自己的SQL知識基礎上才能在沒有他的幫助下開發這些報告。 (順便說一下,不是由DBA,而是由我的老闆。) – DataGirl

回答

1

更新回答

示例代碼創建一個表和工作的解決方案如下。基本上你會做2 EXISTS檢查 - 查看是否有數字比當前數字更高,並且沒有比當前數字更高的數字。

DECLARE @t Table (Store int, Product varchar(100), number int) 
INSERT INTO @t 
VALUES 
(1, 'Widget', 100), 
(1, 'Widget', 101), 
(1, 'Widget', 102), 
(1, 'Widget', 104), 
(2, 'Widget', 201), 
(2, 'Widget', 202), 
(2, 'Widget', 203) 

SELECT Store, Product, t.Number+1 as Missing 
FROM @t t 
WHERE EXISTS (SELECT 1 FROM @t t2 
       WHERE t2.Store = t.Store 
       AND t2.product = t.product 
       AND t2.number > t.number) 
AND Not Exists (SELECT 1 FROM @t t3 
       WHERE t3.Store = t.store 
       AND t3.product = t.product 
       AND t3.number = t.number + 1) 
+0

我想我沒有足夠好地解釋我的問題。小部件本身有數字,所以當你銷售小部件#1時,你銷售的下一個小部件應該是小部件#2。然而;有時候,這種情況不會發生,並且會出售小部件#3 - 小部件#2丟失,並且不在數據庫中。 – DataGirl

+0

@DataGirl - AHHHHHHHHHH更容易檢查。給我一分鐘來發布解決方案。 – JNK

+0

@DataGirl - 發佈工作解決方案。 – JNK

0

創建一個數字表並用比您需要更多的數字填充它。 然後你可以使用基於集合的查詢得到的結果

Create table #temp (product varchar(15), id int) 
insert into #temp 
values ('test', 1), ('test', 3),('test', 4),('test2', 6),('test2', 2),('test2', 10),('test3', 10),('test3', 9),('test3',7),('test4', 1),('test4', 2),('test4', 3) 

create table #product (product varchar (15)) 
insert into #product 
values ('test'),('test2'),('test3'),('test4'), ('test5') 
create table #num (number int) 

insert into #num 
values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15) 

select n.number,p.product from #num n 
cross join #product p 
left join (
select product, max(id)as maxid from #temp group by product)a 
on a.product = p.product 
left join #temp t on n.number = t.id and t.product = p.product 
where n.number <=a.maxid and t.id is null 
order by p.product