2013-12-22 46 views
0

我有3個表:可選連接表中的SQL與可能的空值

DECLARE @PRODUCT TABLE(PRODUCTID INT,TITLE NVARCHAR(MAX),BRANDID INT,SPECID INT) 

DECLARE @SPEC TABLE(SPECID INT,TITLE NVARCHAR(MAX)) 

DECLARE @BRAND TABLE(BRANDID INT,TITLE NVARCHAR(MAX)) 

INSERT INTO @PRODUCT 
SELECT 1,'TV',1,8 UNION ALL 
SELECT 2,'PC',2,12 

INSERT INTO @BRAND 
SELECT 1,'SAMSUN' UNION ALL 
SELECT 2,'GRUNDING' 

INSERT INTO @SPEC 
SELECT 8,'PRICE' UNION ALL 
SELECT 9,'WEIGHT' 

我想從@PRODUCT表導致如果@BRAND@SPEC 至少一個表格有數據。所以,我想用LEFT JOIN這樣的:

SELECT p.* , 
     s.*, 
     b.* 
FROM @PRODUCT p 
     LEFT JOIN @BRAND b ON b.BRANDID = p.BRANDID AND b.BRANDID IS NOT NULL 
     LEFT JOIN @SPEC s ON s.SPECID = p.SPECID AND s.SPECID IS NOT NULL 

,但無法得到期望的結果。對於我提供的數據,我想過濾僅與產品標題電視。所以,我想申請可選加入。我的意思是,如果@BRAND或@SPEC表有數據,或者兩者都有數據,則應根據該條件過濾產品。

任何人都可以幫助我解決這個問題嗎?

編輯 根據要求,我提供了更多的表格數據。

INSERT INTO @PRODUCT 
SELECT 1,'TV',1,8 UNION ALL 
SELECT 2,'PC',2,12 UNION ALL 
SELECT 2,'PHONE',505,10 

INSERT INTO @BRAND 
SELECT 1,'SAMSUN' UNION ALL 
SELECT 2,'GRUNDING' 

INSERT INTO @SPEC 
SELECT 8,'PRICE' UNION ALL 
SELECT 9,'WEIGHT' UNION ALL 
SELECT 10,'SIZE' 

對於這個數據,我只想得到ProductID爲1的產品的行。所以,我只需要在這個例子中選擇這一行。

+0

SPEC和BRAND表中的值現在在語義上並不重要,因爲此示例是原始查詢的簡化版本。我只想指出,我應該從產品表中獲取滿足品牌和規格表的那些標準的數據 –

回答

1

以下作品。我只是試了一下。我唯一改變的是將WHERE s.SPECID IS NOT NULLON CLAUSE移到WHERE CLAUSE。使其在ON CLAUSELEFT JOIN僅限於連接,但仍返回該行。在WHERE CLAUSE中對其進行過濾。

DECLARE @SpecCount INT 
DECLARE @BrandCount INT 

SELECT @SpecCount = COUNT(*) FROM @SPEC 
SELECT @BrandCount = COUNT(*) FROM @BRAND 

SELECT p.*, 
    s.*, 
    b.* 
FROM @PRODUCT p 
LEFT JOIN @BRAND b 
    ON b.BRANDID = p.BRANDID 
LEFT JOIN @SPEC s 
    ON s.SPECID = p.SPECID 
WHERE ((s.SPECID IS NOT NULL OR @SpecCount = 0) 
    AND (b.BRANDID IS NOT NULL OR @BrandCount = 0)) 
+0

這不是期望的結果。 JOIN應該在這些情況下工作:1。當SPEC或BRAND表中的某一個爲空時,2.當三個表中的所有表都有數據時 –

+0

您可以在問題中添加更多行並提供您想要的輸出? –

+0

更新了答案..這是你想要的嗎? –

0

如果我明白你在找什麼,你應該首先進行連接,然後過濾。喜歡的東西:

SELECT 
    p.* , 
    s.*, 
    b.* 
FROM 
    @PRODUCT p 
LEFT JOIN 
    @BRAND b 
ON 
    b.BRANDID = p.BRANDID 
LEFT JOIN 
    @SPEC s 
ON 
    s.SPECID = p.SPECID 
WHERE 
    b.BRANDID IS NOT NULL OR s.SPECID IS NOT NULL 
+0

這會給出一個錯誤... WHERE子句中的b.BRANDID還需要檢查NULL。請看下面的答案。 –

+0

是的,發現並改變了,謝謝。 –

1

如果您對dbo.Product.BRANDIDdbo.Product.SPECID列定義外鍵約束(他們是可信的),那麼你可以檢查是否這兩個值(列)一個非NULL(IS NOT NULL)使用WHERE子句:

SELECT ... 
FROM @PRODUCT p 
     LEFT JOIN @BRAND b ON b.BRANDID = p.BRANDID 
     LEFT JOIN @SPEC s ON s.SPECID = p.SPECID 
WHERE p.BRANDID IS NOT NULL OR p.SPECID IS NOT NULL 
+0

在這種情況下(可信的FKs約束),LEFT JOIN不是必需的。 –

+0

謝謝。但這不是期望的查詢。如果數據在Spec或Brand表格中,或者數據在兩者中,我想要獲得結果集。這就是爲什麼我可以選擇加入 –

+0

@ black123:我不明白你的意見:你可以在SELECT子句中編寫所需的列:'SELECT p.ProductID,p.Title,s.Title AS SpecTitle,b.Title AS BrandTitle,。 ..'。 –