SQL-如果已使用项目,则排除列表中的项目

时间:2019-02-22 19:42:50

标签: sql sql-server tsql

我知道有一个很好的方法可以做到这一点,但是由于某种原因,我无法想到任何方法。我需要返回用户尚未使用的可用促销代码的列表。我打算建立一个包含所有可用促销代码的临时表,然后循环遍历以建立列表,但这似乎是一个可怕的主意。到目前为止,这是我的代码:

DECLARE
@Email AS NVARCHAR(500) = ''
--AS
--BEGIN
    --Build Active Promotions
        SELECT
            Promotion_ID AS 'ID', 
            Promotional_Code, 
            [Description]
        INTO #ActivePromotions
        FROM [dbo].[WBG_Promotional_Code] 
        WHERE
            [Start_Date] < GETDATE() AND
            GETDATE() < [End_Date]

--Build Count
DECLARE @Count AS INT = (SELECT  COUNT(ID) FROM #ActivePromotions)
DECLARE @Tick INT = 0;

--Build List
WHILE @Count < @Tick BEGIN     

    SET @Tick = @Tick + 1;
END;


DROP TABLE #ActivePromotions

-END

这是购买表:

Purchase_ID, 
Email, 
Product_Name, 
Purchase_Date, 
Purchase_Amount, 
Promotional_Code

这是促销代码表

Promotion_ID, 
Promotional_Code, 
Start_Date, 
End_Date, 
Description

一开始我唯一想到的就是对Promotional_Code进行LEFT联接到Purchasing来联接表,并尝试进一步过滤,但无法使它起作用。开放的想法。

2 个答案:

答案 0 :(得分:1)

通过NOT EXISTS关联子查询可能会比使用LEFT JOIN获得更好的性能。

编辑:根据OP的评论和发布的答案扩展查询。

假设:“使用的代码”是来自购买表中与参数化的@Email地址相关联的代码。

WITH usedCodes AS
(
  SELECT 
    Email,
    Promotional_Code
  FROM
    dbo.WBG_Purchase
  WHERE
    Email = @Email
  GROUP BY
    Email,
    Promotional_Code
)
SELECT
    p.Promotion_ID AS 'ID', 
    p.Promotional_Code, 
    p.[Description]
INTO #ActivePromotions
FROM dbo.WBG_Promotional_Code as p
WHERE
    p.[Start_Date] < GETDATE() 
    AND
    GETDATE() < p.[End_Date]
    AND
    NOT EXISTS 
      (SELECT 1 
       FROM usedCodes as uc
       WHERE p.Promotional_Code = uc.Promotional_Code);

CTE将购买表中的数据集限制为与您要发送到过程中的电子邮件地址相关的购买。相关子查询在促销代码表中查找未出现在CTE数据集中的代码。

答案 1 :(得分:0)

我将建议这个答案。我尚未对其进行大量测试,但似乎可以正常工作。

    SELECT
    Promotion_ID AS 'ID', 
    Promotional_Code, 
    [Description]
FROM [dbo].[WBG_Promotional_Code] as c
WHERE
    [Start_Date] < GETDATE() AND
    GETDATE() < [End_Date] AND
    Promotional_Code NOT IN (SELECT [Promotional_Code] FROM [dbo].[WBG_Purchase] as p WHERE p.Promotional_Code IS NOT NULL AND p.Email = @Email)