Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL IF ELSE包含2个变量并连接3个表_Sql - Fatal编程技术网

SQL IF ELSE包含2个变量并连接3个表

SQL IF ELSE包含2个变量并连接3个表,sql,Sql,我是一名C程序员,必须编写一些SQL存储过程,但我不太擅长SQL。我有一个存储过程,它将返回一个基于搜索条件的SKU列表,其中包含两个变量,如果用户没有选择其中一个搜索项,则变量可以为NULL。该列表将返回一个SKU行列表,其中包含搜索变量的匹配列,以及链接表的名称。我建立了一个数据库,其中包含以下三个表,这应该可以更好地解释它: CREATE TABLE [dbo].[SKU]( [SKU_ID] [int] IDENTITY(1,1) NOT NULL, [CATEGORY_ID] [int

我是一名C程序员,必须编写一些SQL存储过程,但我不太擅长SQL。我有一个存储过程,它将返回一个基于搜索条件的SKU列表,其中包含两个变量,如果用户没有选择其中一个搜索项,则变量可以为NULL。该列表将返回一个SKU行列表,其中包含搜索变量的匹配列,以及链接表的名称。我建立了一个数据库,其中包含以下三个表,这应该可以更好地解释它:

CREATE TABLE [dbo].[SKU](
[SKU_ID] [int] IDENTITY(1,1) NOT NULL,
[CATEGORY_ID] [int] NULL,
[MANUFACTURER_ID] [int] NULL,
[SKU_NUMBER_CD] [varchar](100) NOT NULL,
[ACTIVE_IND] [bit] NOT NULL

CREATE TABLE [dbo].[CATEGORY](
[CATEGORY_ID] [int] IDENTITY(1,1) NOT NULL,
[CATEGORY_NUMBER_CD] [varchar](10) NULL,
[CATEGORY_NAME_TXT] [varchar](255) NULL,
[ACTIVE_IND] [bit] NOT NULL

CREATE TABLE [dbo].[MANUFACTURER](
[MANUFACTURER_ID] [int] IDENTITY(1,1) NOT NULL,
[MANUFACTURER_NAME_TXT] [varchar](50) NULL,
[ACTIVE_IND] [bit] NOT NULL
这是我正在尝试使用的存储过程。我想做的是有4种不同的情况,例如@CategoryID和@ManufacturerID中有一个值,其中一个为NULL,而另一个为NULL,以及它们都为NULL。在案例1中,我只想返回那些具有匹配类别和匹配制造商的SKU,在案例2中,我想返回具有匹配类别但制造商不重要的SKU,依此类推。我遇到的问题是,对于案例2中返回的行,我仍然需要从manufacturer表中获取manufacturer\u name\u txt。但是我得到了应该多次返回的每一行,每一行在该列中都有不同的制造商名称

    ALTER PROCEDURE [dbo].[usp_SAL_GetSkuListFiltered]
    @CategoryID int,
    @ManufacturerID int
AS
BEGIN
    SET NOCOUNT ON;

    BEGIN
    --Get SKUs that have a matching Category and a matching Manufacturer
    IF @CategoryID IS NOT NULL AND @ManufacturerID IS NOT NULL
        SELECT k.*, c.CATEGORY_NAME_TXT, m.MANUFACTURER_NAME_TXT
        FROM SKU k, CATEGORY c, MANUFACTURER m
        WHERE k.CATEGORY_ID = @CategoryID 
            AND k.MANUFACTURER_ID = @ManufacturerID
            AND k.CATEGORY_ID = c.CATEGORY_ID
            AND k.MANUFACTURER_ID = m.MANUFACTURER_ID
            AND k.ACTIVE_IND = 1


    --Get SKUs that have a matching Category and any Manufacturer
    ELSE IF @CategoryID IS NOT NULL AND @ManufacturerID IS NULL
        SELECT k.*, c.CATEGORY_NAME_TXT, m.MANUFACTURER_NAME_TXT
        FROM SKU k, CATEGORY c, MANUFACTURER m
        WHERE k.CATEGORY_ID = @CategoryID
            AND k.CATEGORY_ID = c.CATEGORY_ID
            AND k.MANUFACTURER_ID = m.MANUFACTURER_ID
            AND k.ACTIVE_IND = 1


    --Get SKUs that have a matching Manufacturer and any Category
    ELSE IF @CategoryID IS NULL AND @ManufacturerID IS NOT NULL
        SELECT k.*, c.CATEGORY_NAME_TXT, m.MANUFACTURER_NAME_TXT
        FROM SKU k, CATEGORY c, MANUFACTURER m
        WHERE k.MANUFACTURER_ID = @ManufacturerID
            AND k.CATEGORY_ID = c.CATEGORY_ID
            AND k.MANUFACTURER_ID = m.MANUFACTURER_ID
            AND k.ACTIVE_IND = 1

    -- Get all SKUs
    ELSE
        SELECT k.*, c.CATEGORY_NAME_TXT, m.MANUFACTURER_NAME_TXT
        FROM SKU k, CATEGORY c, MANUFACTURER m
        WHERE k.CATEGORY_ID = c.CATEGORY_ID
            AND k.MANUFACTURER_ID = m.MANUFACTURER_ID
            AND k.ACTIVE_IND = 1
    END
END
以下是数据示例:

SKU_ID/CATEGORY_ID/MANUFACTURER_ID/SKU_NUMBER_CD/MANUAL_IND/ACTIVE_ID

1   1   1   BFG56789    False   True

2   1   2   YIR46578    False   True

3   1   3   WER22987    False   True

4   1   3   WXT87654    False   True

5   2   4   TYR44578    False   True

6   2   1   DRE44559    False   True

7   3   2   ZXX44455    False   True

8   4   3   BWE44590    False   True

9   4   2   HGT347474   False   True

12  NULL    NULL    12344   False   True

13  2   NULL    473489  False   True

14  3   NULL    437HHH8 False   True

15  NULL    1   YUXD678 False   True

16  NULL    3   WEW3334 False   True
例如,当我使用以下变量执行存储过程时:

EXEC    @return_value = [dbo].[usp_SAL_GetSkuListFiltered]
    @CategoryID = 2,
    @ManufacturerID = NULL
我将返回两行,SKU_ID 5和6,但不是SKU_ID 13,它在MANUFACTURER_ID字段中有空值。但是,如果我从存储的进程中删除一行,那么我有:

--Get SKUs that have a matching Category and any Manufacturer
ELSE IF @CategoryID IS NOT NULL AND @ManufacturerID IS NULL
    SELECT k.*, c.CATEGORY_NAME_TXT, m.MANUFACTURER_NAME_TXT
    FROM SKU k, CATEGORY c, MANUFACTURER m
    WHERE k.CATEGORY_ID = @CategoryID
        AND k.CATEGORY_ID = c.CATEGORY_ID
        AND k.ACTIVE_IND = 1
然后我返回了12行——SKU_ID 5四次,每个都有不同的制造商名称,我在制造商表中列出了4行,然后SKU_ID 6四次,SKU_ID 13四次


我通过查看站点了解到,使用WHERE语法可能会产生歧义。我正在使用SQL2005。我知道我需要使用左联接或右联接,但我不理解它们。在过去的几天里,我尝试了很多不同的方法,但都没有结果。我就是不懂SQL查询。有人能帮我找出我的逻辑哪里错了吗?

你可能可以让整个过程像这样运行:

SELECT k.*, c.CATEGORY_NAME_TXT, m.MANUFACTURER_NAME_TXT
FROM SKU k
LEFT JOIN CATEGORY c
ON k.CATEGORY_ID = c.CATEGORY_ID
LEFT JOIN MANUFACTURER m
ON k.MANUFACTURER_ID = m.MANUFACTURER_ID
AND k.ACTIVE_IND = 1
WHERE k.CATEGORY_ID = ISNULL(@CategoryID, k.CATEGORY_ID)
AND k.MANUFACTURER_ID = ISNULL(@ManufacturerID, k.MANUFACTURER_ID)

您使用的符号是隐式联接,它们都是内部联接。您的空行被忽略,因为标准指定了一个相等值,并且左侧的制造商ID为空。当一个条件被忽略时,您会得到一个交叉连接-内部连接-为TRUE,这就是为什么您会看到行的乘法

尝试类似的方法不需要多个IF语句:

SELECT k.*, c.CATEGORY_NAME_TXT, m.MANUFACTURER_NAME_TXT
FROM SKU k, CATEGORY c, MANUFACTURER m
WHERE (k.CATEGORY_ID = @CategoryID OR @CategoryID IS NULL)
    AND (k.MANUFACTURER_ID = @ManufacturerID OR @ManufacturerID IS NULL)
    AND (k.CATEGORY_ID = c.CATEGORY_ID OR k.CATEGORY_ID IS NULL)
    AND (k.MANUFACTURER_ID = m.MANUFACTURER_ID OR k.MANUFACTURER_ID IS NULL)
    AND k.ACTIVE_IND = 1
尽管如此,我还是推荐你

我建议您了解更多关于SQL的知识,这里有

使用显式联接:

SELECT k.*, c.CATEGORY_NAME_TXT, m.MANUFACTURER_NAME_TXT
FROM SKU k
LEFT JOIN CATEGORY c -- A left join means a row in K has to exist, but c can be missing
    ON k.CATEGORY_ID = c.CATEGORY_ID
LEFT JOIN MANUFACTURER m
    ON k.MANUFACTURER_ID = m.MANUFACTURER_ID
WHERE (k.CATEGORY_ID = @CategoryID OR @CategoryID IS NULL)
    AND (k.MANUFACTURER_ID = @ManufacturerID OR @ManufacturerID IS NULL)
    AND k.ACTIVE_IND = 1

请注意,如果右侧存在多行,则左连接仍可能导致类似交叉连接的乘法效果。

感谢您的快速响应。当我尝试这段代码时,我只返回了在CATEGORY_ID和MANUFACTURER_ID中都有值的SKU。如果其中一列中有NULL,则不会返回该行。我认为这是因为最后两行不允许在比较两个表时使用空值?感谢您的快速响应。我尝试了这段代码,当我尝试使用CategoryID=2和manufactureId=NULL执行它时,我返回了两个SKU,其中Category和manufactureId都有一个值,但对于制造商ID列中有NULL的SKU,我返回了4行。也许我的想法有点缺陷?理想情况下,我希望返回三行,并且第三个SKU在制造商名称TXT列中有一个空值……谢谢你的链接,我将不得不查看那些SQL书籍。@Bill Tanner我想这是隐式连接的问题-我可能没想清楚-我将发布一个带有显式连接的版本。哦,太棒了,谢谢左连接的工作原理与我的想法相反,我必须研究这个。再次感谢你的帮助。