【问题标题】:INSERT or UPDATE the table from SELECT in sql server从 sql server 中的 SELECT 插入或更新表
【发布时间】:2021-04-29 02:57:31
【问题描述】:

我有一个要求,我必须检查表中是否已经存在营业日期的记录,然后我需要从 select 语句中更新该营业日期的值,否则我必须从选择语句。以下是我目前仅插入的完整查询:

    INSERT INTO 
         gstl_calculated_daily_fee(business_date,fee_type,fee_total,range_id,total_band_count) 
     select
    @tlf_business_date,
    'FEE_LOCAL_CARD',
     SUM(C.settlement_fees),
     C.range_id,
     Count(1)
From
(
    select
        *
    from
        (
            select
                rowNumber = @previous_mada_switch_fee_volume_based_count + (ROW_NUMBER() OVER(PARTITION BY DATEPART(MONTH, x_datetime) ORDER BY x_datetime)),
                tt.x_datetime
            from gstl_trans_temp tt where (message_type_mapping = '0220') and card_type ='GEIDP1' and response_code IN('00','10','11')  and tran_amount_req >= 5000 AND merchant_type NOT IN(5542,5541,4829)
         
        ) A

        CROSS APPLY
            (
                select
                     rtt.settlement_fees,
                     rtt.range_id
                     From gstl_mada_local_switch_fee_volume_based rtt
                    where A.rowNumber >= rtt.range_start
                        AND (A.rowNumber <= rtt.range_end OR rtt.range_end IS NULL)
            ) B 
) C
group by CAST(C.x_datetime AS DATE),C.range_id

我曾尝试使用 if exists,但无法满足上述完整查询。

if exists (select 
                business_date  
          from gstl_calculated_daily_fee 
          where 
          business_date = @tlf_business_date)



UPDATE gstl_calculated_daily_fee
    SET fee_total = @total_mada_local_switch_fee_low
    WHERE fee_type = 'FEE_LOCAL_CARD' 
    AND business_date = @tlf_business_date 

    else

     INSERT INTO 
         

请帮忙。

【问题讨论】:

标签: sql sql-server sql-update sql-insert


【解决方案1】:

您需要一个带有连接的MERGE 语句。

基本上,MERGE 的问题是我们只想合并目标表的一个子集。为此,我们将表预过滤为 CTE。我们也可以把源表作为一个CTE。

在使用 CTE 时写 MERGE 时要非常小心。您必须确保将 CTE 中的目标完全过滤到要合并的行,然后使用 ON

匹配行
;with source as (
    select
        business_date = @tlf_business_date,
        fee_total = SUM(C.settlement_fees),
        C.range_id,
        total_band_count = Count(1)
    From
    (
            select
                rowNumber = @previous_mada_switch_fee_volume_based_count + (ROW_NUMBER() OVER(PARTITION BY DATEPART(MONTH, x_datetime) ORDER BY x_datetime)),
                tt.x_datetime
            from gstl_trans_temp tt where (message_type_mapping = '0220') and card_type ='GEIDP1' and response_code IN('00','10','11')  and tran_amount_req >= 5000 AND merchant_type NOT IN(5542,5541,4829)
         
    ) A

    CROSS APPLY
    (
            select
                 rtt.settlement_fees,
                 rtt.range_id
            From gstl_mada_local_switch_fee_volume_based rtt
            where A.rowNumber >= rtt.range_start
                AND (A.rowNumber <= rtt.range_end OR rtt.range_end IS NULL)
    ) B 
    group by CAST(A.x_datetime AS DATE), B.range_id
),

target as (
    select 
        business_date,fee_type,fee_total,range_id,total_band_count
    from gstl_calculated_daily_fee 
    where business_date = @tlf_business_date AND fee_type = 'FEE_LOCAL_CARD'
)

MERGE INTO target t
USING source s
ON t.business_date = s.business_date AND t.range_id = s.range_id

WHEN NOT MATCHED BY TARGET THEN INSERT
    (business_date,fee_type,fee_total,range_id,total_band_count) 
    VALUES
    (s.business_date,'FEE_LOCAL_CARD', s.fee_total, s.range_id, s.total_band_count)

WHEN MATCHED THEN UPDATE SET
    fee_total = @total_mada_local_switch_fee_low
;

MERGE 语句的工作方式是,它基本上在源表和目标表之间执行FULL JOIN,使用ON 子句进行匹配。然后它将各种条件应用于生成的连接并基于它们执行语句。

您可以执行三种可能的条件:
WHEN MATCHED THEN
WHEN NOT MATCHED [BY TARGET] THEN
WHEN NOT MATCHED BY SOURCE THEN
以及三个可能的语句,它们都引用了目标表:UPDATEINSERTDELETE(显然并非所有情况都适用)。

一个常见的问题是我们只想考虑目标表的一个子集。对此有多种可能的解决方案:

我们可以在 WHEN MATCHED 子句中过滤匹配,例如WHEN MATCHED AND target.somefilter = @somefilter。不过,这通常会导致全表扫描。

相反,我们将过滤后的目标表放入 CTE,然后将 MERGE 放入其中。 CTE 必须遵循Updatable View 规则。我们还必须选择我们希望插入或更新到的所有列。但是我们必须确保我们完全过滤了目标,否则如果我们发出DELETE,那么目标表中的所有行都将被删除。

【讨论】:

  • 谢谢,它成功了。你能解释一下这个查询以及它是如何工作的吗?
猜你喜欢
  • 2014-01-03
  • 1970-01-01
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 2011-04-16
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多