2011-10-03 80 views
2

對於每個BoxId和Revision具有單個UnitTypeId爲1且單個UnitTypeId爲2且具有NULL SetNumber的唯一組合,分配SetNumber爲1.根據多列條件在同一個表內創建「集合」

表和數據設置:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[UnitTypes]') AND type in (N'U')) 
Drop Table dbo.UnitTypes 
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Tracking]') AND type in (N'U')) 
DROP TABLE [dbo].[Tracking] 
GO 
CREATE TABLE dbo.UnitTypes 
    (
    Id int NOT NULL, 
    Notes varchar(80) 
    ) 
GO 
CREATE TABLE dbo.Tracking 
    (
    Id int NOT NULL IDENTITY (1, 1), 
    BoxId int NOT NULL, 
    Revision int NOT NULL, 
    UnitValue int NULL, 
    UnitTypeId int NULL, 
    SetNumber int NULL 
    ) 
GO 
ALTER TABLE dbo.Tracking ADD CONSTRAINT 
    PK_Tracking PRIMARY KEY CLUSTERED 
    (
    Id 
    ) 
GO 
Insert Into dbo.UnitTypes (Id, Notes) Values (1, 'X Coord'), 
              (2, 'Y Coord'), 
              (3, 'Weight'), 
              (4, 'Length') 
Go 
Insert Into dbo.Tracking (BoxId, Revision, UnitValue, UnitTypeId, SetNumber) 
       Values (1165, 1, 150, 1, NULL), 
        (1165, 1, 1477, 2, NULL), 
        (1165, 1, 31, 4, NULL), 
        (1166, 1, 425, 1, 1), 
        (1166, 1, 1146, 2, 1), 
        (1166, 1, 438, 1, NULL), 
        (1166, 1, 1163, 2, NULL), 
        (1167, 1, 560, 1, NULL), 
        (1167, 1, 909, 2, NULL), 
        (1167, 1, 12763, 3, NULL), 
        (1168, 1, 21, 1, NULL), 
        (1168, 1, 13109, 3, NULL) 

理想的結果將是:

Id BoxId Revision UnitValue UnitTypeId SetNumber 
1 1165   1   150   1   1 
2 1165   1   1477   2   1 
3 1165   1   31   4   1 
4 1166   1   425   1   1 
5 1166   1   1146   2   1 
6 1166   1   438   1  NULL <--NULL Because there is already an existing Set 
7 1166   1   1163   2  NULL <--NULL Because there is already an existing Set 
8 1167   1   560   1   1 
9 1167   1   909   2   1 
10 1167   1  12763   3   1 
11 1168   1   21   1  NULL <--NULL Because there is not exactly one UnitTypeId of 1 and exactly one UnitTypeId of 2 for this BoxId\Revision combination. 
12 1168   1  13109   3  NULL <--NULL Because there is not exactly one UnitTypeId of 1 and exactly one UnitTypeId of 2 for this BoxId\Revision combination. 

編輯: 問題是,如何使用純TSQL更新SetNumber,給定上面的約束條件?

+0

問題是如何使用sql來完成此操作。我嘗試了很多東西,但總是以臨時表格結束。我正在尋找執行此更新的最有效方法。 –

+0

就像在學校的數學課上,最好**展示你的作品**。如果看起來你沒有做任何事情,只是來找SO發佈一個需求清單,讓別人爲你做所有事情,你就不太可能從更有經驗的人那裏得到幫助。 – JNK

+0

優秀點。儘管我現在整天都在對付這個問題,並且出於絕望的考慮,我轉而希望有人有一個聰明的解決方案。 –

回答

2

如果我正確理解你的問題,你可以用它要求所有條件都滿足的子查詢做到這一點:

update t1 
set  SetNumber = 1 
from dbo.Tracking t1 
where SetNumber is null 
     and 1 = 
     (
     select case 
       when count(case when t2.UnitTypeId = 1 then 1 end) <> 1 then 0 
       when count(case when t2.UnitTypeId = 2 then 1 end) <> 1 then 0 
       when count(t2.SetNumber) <> 0 then 0 
       else 1 
       end 
     from dbo.Tracking t2 
     where t1.BoxId = t2.BoxId 
       and t1.Revision = t2.Revision 
     ) 

count(t2.SetNumber)是有點棘手:其中SetNumbernull這隻會計算行。所以這符合不存在與其他組相同的標準(BoxId, Revision)的標準。

+0

我喜歡這種簡單。我的程序是針對子查詢編寫的,我的大腦將它們濾除爲可能的解決方案。我正在處理小數據集,因此性能不成問題。我感謝您的幫助。 –

1

試試看,它會返回與您給出的結果相同的結果。語句WITH設置了一個CTE來查詢。 ROW_NUMBER()功能是分區功能,它可以做你想做的事:

;WITH BoxSets AS (
SELECT 
    ID 
    ,BoxId 
    ,Revision 
    ,UnitValue 
    ,UnitTypeId 
    ,CASE WHEN UnitTypeId IN (1,2) THEN 1 ELSE 0 END ValidUnit 
    ,ROW_NUMBER() OVER (PARTITION BY BoxID,UnitTypeID ORDER BY BoxID,UnitTypeID,UnitValue) SetNumber 
FROM Tracking 
) 

SELECT 
    b.ID 
    ,b.BoxId 
    ,b.Revision 
    ,b.UnitValue 
    ,b.UnitTypeId 
    ,CASE ISNULL(b1.ValidUnits,0) WHEN 0 THEN NULL ELSE CASE b.SetNumber WHEN 1 THEN b.SetNumber ELSE NULL END END 
FROM BoxSets AS b 
LEFT JOIN (SELECT 
      BoxID 
      ,SUM(ValidUnit) AS ValidUnits 
      FROM BoxSets 
      GROUP BY BoxId 
      HAVING SUM(ValidUnit) > 1) AS b1 ON b.BoxId = b1.BoxId 
+0

OP要求標記何時只有一個'1'和一個'2'。這個答案會接受具有兩個甚至三個「UnitTypeId = 1」的組? – Andomar

+0

簡單的修復,只是在'CASE'語句中顛倒了條件。 – Wil

+0

這非常接近,但並不排除BoxId 1166系列。 –

相關問題