2016-04-15 4 views
1

奇妙なタイトルのため申し訳ありませんが、私は難解な時間をより記述的なものと考えています。t-sql奇数結合要件

私はあなたは、T-SQLで次のことを実行したい方法を知っておく必要があります。

はあなたがこれらのエンティティのために期待する典型的な1対多の関係では、次の3つのテーブルを持っている想像してみてください。 Itemsテーブル上の「SpecialBooleanFlag」(一瞬でその上より)しかし注意:

Customers: CustomerId, CustomerName, (etc....) 
Orders: OrderId, OrderDtm, CustomerId (etc.....) 
Items:  ItemId, ItemDescripion, OrderId, **SpecialBooleanFlag** 

これは、この記事で説明するの奇妙な要件のように、私の手段を超えて聞こえますが、あなたの上司が書くためにあなたを求めて想像これまでに購入したアイテムごとに顧客の完全な注文履歴のすべてを返すクエリ。ただし、の場合、お客様の注文のの1つにSpecialBooleanFlag = 1の商品がある場合、その商品はのようにのように表示されます。

したがって、顧客がSpecialBooleanFlag = 1のアイテムを注文したことがない場合、結果の数は、注文したアイテムの合計数と等しくなければなりません。ただし、5つの注文を出してその注文のうちの1つにSpecialBooleanFlag = 1のアイテムがある場合、結果カウントは5 + 4になり、4つの余分な行がフラグ付きアイテムを実際には一致しなかった4つの注文に関連付けますアイテム。

私はこれをカーソル/ループで一度達成しましたが、解決策が遅すぎます。可能であれば、古い古いセット操作で行う方法を知る必要があります。

編集:

SELECT CustomerName as Name, CustomerId, OrderId, ItemDescription, SpecialBooleanFlag 
FROM Customers C 
JOIN Orders O on C.CustomerId = O.CustomerId 
JOIN Items I on O.OrderId = I.OrderId 
WHERE C.CustomerId = 99 

結果:全部で合計9つのアイテムと

CustomerName  CustomerId  OrderId  ItemDescription SpecialBooleanFlag 
George Washington 99    1   Shoes    0 
George Washington 99    1   Shirt    0 
George Washington 99    1   Tie    0 
George Washington 99    2   Socks    0 
George Washington 99    2   Hat    1  
George Washington 99    2   Bowtie    0 
George Washington 99    3   Green Coat   0 
George Washington 99    3   Blue Coat   0 
George Washington 99    3   Red Coat   0 

ので、顧客が持っていた3件の受注たとえば、次のクエリ/結果セットを想像してみてください。帽子は "特別な"ものだが、注文番号2にあった。私はそれが毎回注文されたかのように見せたい。この結果セットは私が探しているものです。帽子は、それがむしろアイテムと注文IDの1と3の間に関連性よりも、フラグが立てられたという事実に基づく命令1および3上に示しています

CustomerName  CustomerId  OrderId  ItemDescription SpecialBooleanFlag 
    George Washington 99    1   Shoes    0 
    George Washington 99    1   Shirt    0 
    George Washington 99    1   Tie    0 
    George Washington 99    1   Hat    1 
    George Washington 99    2   Socks    0 
    George Washington 99    2   Hat    1  
    George Washington 99    2   Bowtie    0 
    George Washington 99    3   Green Coat   0 
    George Washington 99    3   Blue Coat   0 
    George Washington 99    3   Red Coat   0 
    George Washington 99    3   Hat    1 

これはより理にかなっていますか?

+2

いくつかのサンプルデータと予想される結果を示しています。 –

+0

ここから始めましょう。 https://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/ –

+0

あなたは数量または注文/商品のリストをお探しですか? – dbbri

答えて

0

2ワード、CROSSが適用されます。

IF OBJECT_ID('tempdb..#Customers') IS NOT NULL DROP TABLE #Customers 
IF OBJECT_ID('tempdb..#Orders') IS NOT NULL DROP TABLE #Orders 
IF OBJECT_ID('tempdb..#Items') IS NOT NULL DROP TABLE #Items 

CREATE TABLE #Customers (CustomerId INT, CustomerName varchar(255)) 
CREATE TABLE #Orders (OrderId INT, OrderDtm DateTime, CustomerId INT) 
CREATE TABLE #Items (ItemId INT, ItemDescripion VARCHAR(255), OrderId INT, SpecialBooleanFlag BIT) 

INSERT INTO #Customers (CustomerId, CustomerName) 
VALUES (1,'Customer1') 
,(2,'Customer2') 
,(3,'Customer3') 
,(4,'Customer4') 

INSERT INTO #Orders (OrderId, OrderDtm, CustomerId) 
VALUES (1,'2016-01-01',1) 
,(2,'2016-01-02',1) 
,(3,'2016-01-03',1) 
,(4,'2016-01-04',2) 
,(5,'2016-01-05',2) 
,(6,'2016-01-06',2) 
,(7,'2016-01-07',3) 
,(8,'2016-01-08',3) 
,(9,'2016-01-09',3) 
,(10,'2016-01-10',4) 

INSERT INTO #Items (ItemId, ItemDescripion, OrderId, SpecialBooleanFlag) 
VALUES (1,'Order1Item1',1,0) 
,(2,'Order1Item2',1,0) 
,(3,'Order1Item3',1,0) 
,(1,'Order2Item1',2,0) 
,(2,'Order2Item2',2,0) 
,(1,'Order3Item1',3,0) 
,(1,'Order4Item1',4,0) 
,(2,'Order4Item2',4,0) 
,(3,'Order4Item3',4,1) 
,(1,'Order5Item1',5,0) 
,(2,'Order5Item2',5,0) 
,(1,'Order6Item1',6,0) 

--DECLARE @CustomerId INT = 1 -- no SpecialBooleanFlag 
DECLARE @CustomerId INT = 2 -- has SpecialBooleanFlag 

SELECT C.CustomerId, C.CustomerName,O.OrderId,O.OrderDtm,I.ItemId,I.ItemDescripion,SpecialBooleanFlag 
FROM #Customers C 
JOIN #Orders O on C.CustomerId = O.CustomerId 
JOIN #Items I on O.OrderId = I.OrderId 
WHERE C.CustomerId = @CustomerId 
AND SpecialBooleanFlag != 1 
UNION 
SELECT C.CustomerId, C.CustomerName,O2.OrderId,O.OrderDtm,I.ItemId,I.ItemDescripion,SpecialBooleanFlag 
FROM #Customers C 
JOIN #Orders O on C.CustomerId = O.CustomerId 
JOIN #Items I on O.OrderId = I.OrderId 
CROSS APPLY (SELECT * FROM #Orders O2 WHERE O2.CustomerId = C.CustomerId) O2 
WHERE C.CustomerId = @CustomerId 
AND SpecialBooleanFlag = 1 
+0

ビンゴ。魅力のように動作します。 – Sean

1

私はこのような何かが動作するはずだと思う:

SELECT c.CustomerName, c.CustomerId, o.OrderId, i.ItemDescription, i.SpecialBooleanFlag 
FROM Customers c 
LEFT JOIN Orders o on c.CustomerId = o.CustomerId 
LEFT JOIN Items i on o.OrderId = i.OrderId OR EXISTS 
    (SELECT 1 FROM orders o1 JOIN items i1 ON o1.OrderId = i1.OrderId 
    WHERE o1.CustomerId = c.CustomerId 
     and i.ItemId = i1.ItemId 
     and i1.SpecialBooleanFlag = 1) 
0
SELECT C.CustomerName AS Name, 
     C.CustomerId, 
     O.OrderId, 
     I.ItemDescripion, 
     I.SpecialBooleanFlag 
FROM #Customers C 
     JOIN #Orders O ON C.CustomerId = O.CustomerId 
     JOIN #Items I ON O.OrderId = I.OrderId 
WHERE C.CustomerId = 99 
UNION 
SELECT C.CustomerName AS Name, 
     C.CustomerId, 
     O.OrderId, 
     I.ItemDescripion, 
     I.SpecialBooleanFlag 
FROM #Customers C 
     JOIN #Orders O ON C.CustomerId = O.CustomerId 
     FULL OUTER JOIN #Items I ON I.SpecialBooleanFlag = 1 
WHERE C.CustomerId = 99