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

I을 나는 아마도 내 쿼리로 올바른 방향으로 가고 있지 않다는 것을 알고 있지만, 필요한 결과를 얻기 위해 그것을 고치는 것에 대한 방향을 얻을 수 있기를 바랬다.

감사

편집 :

특정 요구 사항 (I이 포함 생각하지만 난하지 않았다 나타납니다) -이 아닌 시스템의 차지 모든 항목의 반환 목록. 1) MissingOrVoid에있는 해당 항목 유형 테이블의 항목 (누락되거나 제거 된 알려진 항목) 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 

테이블 :

,275,212,525,959,743,210

편집 2 :

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을 제공했다면 더 오래 사용할 수있게되었습니다. –

+0

해당 항목이 포함되도록 편집되었습니다. 또한 그것을 수행하는 방법을 설명하는 데 도움이 될 수있는 C#에서 해킹 된 함께 포함 된 방법 포함 – Robert

답변

4

이 경우에 매우 도움이 될 수 master..spt_values라는 기성품 번호 테이블이있다 : 여기에 어쩌면 도움의 믿을 수 없을만큼 비효율적 인 C# 및 그 일의의 LINQ 방법 만입니다. 그러나 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 

subselect는이 lowrangehighrange에 의해 정의 된 항목 ID와 항목 전체 목록으로 Inventory 테이블을 확장 (숫자 표가 유용 곳입니다) :

여기 방법입니다. 그런 다음 얻은 목록을 다른 세 테이블과 비교하여 항목에있는 항목을 찾아서 제외합니다. 나머지 항목은 '누락 된 항목'목록을 구성합니다.

+0

이것은 내가 찾고있는 종류의 대답입니다. 하나, 그것은 올바른 방향으로 나를 넣어. 둘째, 내가 생각하고 있지 않은 방식으로 솔루션에 다가 섰다. (매우 깔끔하게). 항목 번호는 최대 9999999까지 올라갈 수 있으므로 생성 번호 표가 필요합니다. – Robert

+0

주석 블록이 일찍 중단되었습니다. 고맙습니다. – Robert

+0

@ 로버트 : 도움이되어 기쁘다. 그리고 저는 방금 실수로 실수를 저지른 것으로 나타났습니다. 'v.number BETWEEN 0 and i.highrange AND i.lowrange' 비트는 구문 분석이 될 수 없으며 실제로는 v.number BETWEEN 0과 i.highrange - i.lowrange입니다. 그것을 수정했습니다. –