在相关的产品折扣表中插入最多 10 个缺失的产品

Chr*_*777 3 sql-server t-sql

我有两个表:productsproducts_discounts。如果某个产品被指定为“前 10 名”产品,并且在 中缺少定义的折扣products_discounts,我想products_discounts为每个缺少的记录插入一条记录。插入的值将由product_idINSERT INTO中的和另外两个硬编码值组成。

产品
id、product_id、名称、top_ten

Products_Discounts
id、product_id、discount_amount、discount_description

以下是我计划如何手动执行此操作,但由于我将每年重复此过程几次,因此我想看看这是否可以通过几行 SQL 完成。

(1) 获取符合我的条件的产品列表。

SELECT p.product_id, pd.discount_amount FROM products AS p
LEFT OUTER JOIN products_discounts AS pd
    ON p.product_id = pd.product_Id
WHERE p.top_ten = 1
    AND pd.product_id IS NULL
Run Code Online (Sandbox Code Playgroud)

(2) 使用文本编辑器构建每个单独的 INSERT INTO 语句。我会使用步骤 1 的输出来获取product_ids 但其他两个值将保持不变(硬编码)。

INSERT INTO products_discounts (product_id, discount_amount, discount_description)
VALUES ('<product_id goes here>', 10, 'Top 10 Product')
Run Code Online (Sandbox Code Playgroud)

这些步骤可以组合成几行SQL吗?

Han*_*non 6

这可能会做你想做的:

SELECT 'INSERT INTO products_discounts (product_id, discount_amount, discount_description)
VALUES (''' + CONVERT(varchar(30), p.product_id) + ''', 10, ''Top 10 Product'')
'
FROM products AS p
LEFT OUTER JOIN products_discounts AS pd
    ON p.product_id = pd.product_Id
WHERE p.top_ten = 1
    AND pd.product_id IS NULL;
Run Code Online (Sandbox Code Playgroud)

它为所有前 10 名没有产品折扣的产品生成报表。无需在 Excel 中执行此操作。只需将结果复制并粘贴到 SSMS 中的新查询窗口中并运行它。话虽如此,您可能希望自动化此过程,这可以使用这样的游标来完成:

DECLARE @cmd nvarchar(max);
DECLARE cur CURSOR LOCAL FORWARD_ONLY STATIC
FOR
SELECT 'INSERT INTO products_discounts (product_id, discount_amount, discount_description)
VALUES (''' + CONVERT(varchar(30), p.product_id) + ''', 10, ''Top 10 Product'')
'
FROM products AS p
LEFT OUTER JOIN products_discounts AS pd
    ON p.product_id = pd.product_Id
WHERE p.top_ten = 1
    AND pd.product_id IS NULL;

OPEN cur;
FETCH NEXT FROM cur INTO @cmd;
WHILE @@FETCH_STATUS = 0
BEGIN
    EXEC sys.sp_executesql @cmd;
    FETCH NEXT FROM cur INTO @cmd;
END
CLOSE cur;
DEALLOCATE cur;
Run Code Online (Sandbox Code Playgroud)

或者在基于集合的方法中,像这样:

DECLARE @cmd nvarchar(max);
SELECT @cmd = CASE WHEN @cmd IS NULL THEN N'' ELSE @cmd END 
    + N'INSERT INTO products_discounts (product_id, discount_amount, discount_description)
VALUES (''' + CONVERT(varchar(30), p.product_id) + ''', 10, ''Top 10 Product'')
'
FROM products AS p
LEFT OUTER JOIN products_discounts AS pd
    ON p.product_id = pd.product_Id
WHERE p.top_ten = 1
    AND pd.product_id IS NULL;

EXEC sys.sp_executesql @cmd;
Run Code Online (Sandbox Code Playgroud)


Aar*_*and 6

我很难理解为什么你不能这样做:

INSERT dbo.products_discounts (product_id, discount_amount, discount_description)
SELECT p.product_id, 10, 'Top 10 Product'
FROM dbo.products AS p
LEFT OUTER JOIN dbo.products_discounts AS pd
     ON p.product_id = pd.product_Id
WHERE p.top_ten = 1
  AND pd.product_id IS NULL;
Run Code Online (Sandbox Code Playgroud)

实际上,更直观地说,恕我直言:

INSERT dbo.products_discounts (product_id, discount_amount, discount_description)
SELECT p.product_id, 10, 'Top 10 Product'
FROM dbo.products AS p
WHERE p.top_ten = 1 
AND NOT EXISTS
(
   SELECT 1 FROM dbo.products_discounts AS pd
     WHERE p.product_id = pd.product_Id
);
Run Code Online (Sandbox Code Playgroud)

是不是因为折扣金额(10)因产品而异?与我们分享您使用哪些规则来确定折扣是否应该不是10。如果您不能定义这些,那么 SQL Server 也不能(动态 SQL、循环或游标等也不能)。