2011-02-25 51 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