2013-12-22 107 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,。 ..'。 –