2011-02-25 68 views
1

Creating a SQL query that performs math with variables from multiple tablesSQL查詢基於多個硬編碼範圍

這個問題,我問以前會有點幫助儘可能佈局,爲節省時間起見,我將包括重要的位,並添加選擇缺失記錄

的表會是什麼樣子樣機:對於有關這一方案的更多細節

庫存

ID | lowrange | highrange | ItemType 
---------------------------------------- 
1 | 15  | 20  | 1 
2 | 21  | 30  | 1 
3 | null  | null  | 1 
4 | 100  | 105  | 2 

小姐ingOrVoid

ID | Item | Missing | Void 
--------------------------------- 
1 | 17 | 1  | 0 
1 | 19 | 1  | 0 
4 | 102 | 0  | 1 
4 | 103 | 1  | 0 
4 | 104 | 1  | 0 

TableWithDataEnteredForItemType1

InventoryID| ItemID | Detail1 | Detail2 | Detail3 
------------------------------------------------- 
1   | 16  | Some | Info | Here 
1   | 18  | More | Info | Here 
1   | 20  | Data | Is  | Here 
2   | 21  | .... | .... | .... 
2   | 24  | .... | .... | .... 
2   | 28  | .... | .... | .... 
2   | 29  | .... | .... | .... 
2   | 30  | .... | .... | .... 

TableWithDataEnteredForItemType2

InventoryID| ItemID | Col1 | Col2 | Col3 
---------------------------------------- 
4   | 101 | .... | .... | .... 

我嘗試這一點。我知道這是不是功能,但它說明了什麼我想要做的,我個人還沒有看到寫了這樣的事情之前:

SELECT CASE WHEN (I.ItemType = 1) THEN SELECT TONE.ItemID FROM 
    TableWithDataEnteredForItemType1 TONE WHEN (I.ItemType = 2) 
    THEN SELECT TTWO.ItemID FROM TableWithDataEnteredForItemType2 
    TTWO END AS ItemMissing Inventory I JOIN CASE WHEN (I.ItemType = 1) THEN 
    TableWithDataEnteredForItem1 T WHEN (I.ItemType = 2) THEN 
    TableWithDataEnteredForItem2 T END ON 
    I.ID = T.InventoryID WHERE ItemMissing NOT BETWEEN IN (SELECT 
    I.lowrange FROM Inventory WHERE I.lowrange IS NOT NULL) AND IN 
    (SELECT I.highrange FROM Inventory WHERE I.highrange IS NOT NULL) 
    AND ItemMissing NOT IN (SELECT Item from MissingOrVoid) 

結果應該是:

ItemMissing 
---- 
15 
22 
23 
25 
26 
27 
105 

我知道我可能甚至沒有在正確的方向與我的查詢,但我希望我可以得到一些方向,以解決它得到所需的結果。

感謝

編輯:

具體要求(我想這包括,但似乎我沒有) - 不佔系統中的所有項目的回報清單。有兩種方法可以解釋:1)位於MissingOrVoid中的相應ItemType表2)中的條目(已知項目丟失或被刪除)。

DDL(我不得不看這件事,因爲我不知道發生了什麼這裏是指是,我很少有經驗通過創建腳本表,這將可能是僞DDL):

庫存

ID - int, identifier/primary key, not nullable 
lowrange - int, nullable 
highrange - int, nullable 
itemtype - int, not nullable 

MissingOrVoid

ID - int, foreign key for Inventory.ID, not nullable 
Item - int, identifier/primary key, not nullable 
missing - bit, not nullable 
void - bit, not nullable 

桌項目類型:

IntenvoryID - int, foreign key for Inventory.ID, not nullable 
ItemID - int, primary key, not nullable 
Everything else - not needed for querying, just data about the item (included 
    to show that the tables aren't the same content) 

編輯2:這是一個令人難以置信的低效率的C#和做的LINQ的方式,但也許有些幫助:

List<int> Items = new List<int>(); 
List<int> MoV = (from c in db.MissingOrVoid Select c.Item).ToList(); 
foreach (Table...ItemType1 row in db.Table...ItemType1) 
    Items.Add(row.ItemID); 
foreach (Table...ItemType2 row in db.Table...ItemType2) 
    Items.Add(row.ItemID); 
List<Range> InventoryRanges = new List<Range>(); 
foreach (Inventory row in db.Inventories) 
{ 
    if (row.lowrange != null && row.highrange != null) 
     InventoryRanges.Add(new Range(row.lowrange, row.highrange)); 
} 

foreach (int item in Items) 
{ 
    foreach (Range range in InventoryRanges) 
    { 
     if (range.lowrange <= item && range.highrange >= item) 
      Items.Remove(item); 
    } 
    if (MoV.Contains(item)) 
     Items.Remove(item); 
} 

return Items; 
+0

我懷疑你可能需要一個輔助數字表上的外連接。然而,在這個問題目前的形式中,我可以給予的答案多得多。如果您簡化了您的要求並提供了一些DDL,我會更傾向於花費更長的時間! – 2011-02-25 16:15:07

+0

editted包括這些項目。還包括一個黑客一起在c#中做這件事的方式,這可能有助於說明一種做法 – Robert 2011-02-25 17:17:35

回答

4

有一個現成的數字表稱爲master..spt_values,這可能是在這種情況下非常有用。但請注意,如果lowrangehighrange之間的距離不能超過2047,則可以使用此表,否則請創建,填充並使用您自己的數字表。

這裏的方法:

SELECT 
    ItemMissing = i.Item 
FROM (
    SELECT 
    i.ID, 
    Item = i.lowrange + v.number, 
    i.ItemType 
    FROM Inventory i 
    INNER JOIN master..spt_values v 
     ON v.type = 'P' AND v.number BETWEEN 0 AND i.highrange - i.lowrange 
) inv 
    LEFT JOIN MissingOrViod m 
    ON inv.ID = m.ID AND inv.Item = m.Item 
    LEFT JOIN TableWithDataEnteredForItem1 t1 ON inv.ItemType = 1 
    AND inv.ID = t1.InventoryID AND inv.Item = t1.ItemID 
    LEFT JOIN TableWithDataEnteredForItem2 t2 ON inv.ItemType = 2 
    AND inv.ID = t2.InventoryID AND inv.Item = t2.ItemID 
WHERE m.ID IS NULL AND t1.InventoryID IS NULL AND t2.InventoryID IS NULL 

子選擇擴展Inventory表成一個完整的項目清單,由lowrangehighrange定義項ID(這是其中的數字表就派上用場了)。然後將獲得的列表與其他三個表進行比較,以查找並排除其中存在的項目。其餘項目則構成「缺少物品」清單。

+0

這是我正在尋找的答案。其一,它使我朝着正確的方向前進。第二,它正在以我沒有想到的方式接近解決方案(並且非常乾淨地完成)。物品號碼可以達到9999999,因此需要創建號碼錶。 – Robert 2011-02-28 16:38:14

+0

評論區塊提前停止。意味着添加謝謝。 – Robert 2011-02-28 16:38:51

+0

@羅伯特:很高興能有所幫助。我剛剛注意到,我的解決方案中存在一個無意的錯誤。 'v.number BETWEEN 0和i.highrange AND i.lowrange'位甚至不能被語法分析,實際上應該是'v.number BETWEEN 0和i.highrange - i.lowrange'。修正了。 – 2011-02-28 18:41:13