【问题标题】:Insert into table only distinct rows?仅插入表中不同的行?
【发布时间】:2021-05-11 17:56:57
【问题描述】:

我有临时表#A,其中包含:

ID        RevID     Designation      ParentID     Amount
--------------------------------------------------------    
100       500       Test1            300          5000
250       500       Test2            360          5000
410       500       Test3            580          5000

我还有一个临时表#B,其中包含:

ID        RevID     Text        Amount
--------------------------------------  
900       500       Test100      6500

我要做的是插入表#B 中的内容,而不会由于基于 RevID 的左连接而重复行。我只关心将表 #B 中的 RevID 和 Amount 引入表 #A 中的新行,并保持其他列与表 #A 中具有匹配 RevID 的任何行相同。

我正在尝试通过以下方式插入此表:

INSERT INTO #A (ID, RevID, Designation, ParentID, Amount)
    SELECT DISTINCT
        a.ID,
        a.RevID,
        b.Text,
        a.ParentID,
        b.Amount
    FROM 
        #B b
    LEFT JOIN
        #A a ON b.RevID = a.RevID

我的理想结果如下,它将表#B 中的一行添加到表#A 中,但由于表#A 中的三行具有相同的 RevID,因此没有添加三次:

ID        RevID     Designation      ParentID     Amount

100       500       Test1            300          5000
250       500       Test2            360          5000
410       500       Test3            580          5000
100       500       Test100          300          6500

我认为我不能使用联合,因为表 #A 可能包含其他 RevID,而且表 #B 不包含与表 #A 相同的列,因此我需要与表 #B 连接,并且表 #B 中存在匹配 RevID,只将该行从表#B 带入表#A 一次。

【问题讨论】:

  • JOINUNION ALL?
  • 为什么text 在您的SELECT 中而不是您的预期结果或样本数据?
  • 那是我的错字,我已经在表格#B中更正了

标签: sql sql-server tsql insert sql-insert


【解决方案1】:

这可以很容易地使用cross apply 来选择单个匹配行:

insert into #a (Id, RevId, Designation, ParentId, Amount)
select a.Id, a.RevId, b.[Text], a.ParentId, b.Amount
from #b b
cross apply (
    select top(1) a.Id, a.RevId, a.ParentId
    from #a a
    where a.RevId=b.RevId
    order by a.Id
)a

【讨论】:

    【解决方案2】:

    你可以这样做:

    INSERT INTO #A (ID, RevID, Designation, ParentID, Amount)
     SELECT
      (SELECT TOP 1 id FROM #A a WHERE a.RevId = b.RevId),
      b.RevID,
      b.Text,
      (SELECT TOP 1 ParentId FROM #A a WHERE a.RevId = b.RevId)
      b.Amount
     FROM 
      #B b
    

    这并不漂亮,但我认为从您的描述中非常符合逻辑。从 B 中获取行并保持“其他列与表 #A 中具有匹配 RevID 的任何行相同”

    或者,我可能会建议:

    INSERT INTO #A (ID, RevID, Designation, ParentID, Amount)
     SELECT
      a.ID,
      a.RevID,
      b.Text,
      a.ParentID,
      b.Amount
     FROM 
      #B b
      LEFT JOIN
      (
       SELECT a.RevId, MAX(a.ID) ID, MAX(a.ParentID) ParentID
       FROM #A a
       GROUP BY RevId
      ) a ON b.RevID = a.RevID
    

    内部查询从#A 获取每个 RevId 一行,具有任意 ID 和 ParentID。这可以与#B 连接而不会创建重复项。

    【讨论】:

      【解决方案3】:

      考虑到您只关心从 #B 到 #A 添加不同的 RevID 和 Amount 列,而其余列并不重要,您可以尝试以下查询并检查它是否满足您的所有条件,

      INSERT INTO #A (ID, RevID, Designation, ParentID, Amount)
      SELECT (SELECT TOP 1 #A.ID FROM #A) ID, a.RevID,(SELECT TOP 1 #A.Designation FROM #A) Designation,(SELECT TOP 1 #A.ParentID FROM #A) ParentID,b.Amount FROM  #B b JOIN #A a ON b.RevID = a.RevID
      EXCEPT
      SELECT (SELECT TOP 1 #A.ID FROM #A) ID,RevID,(SELECT TOP 1 #A.Designation FROM #A) Designation,(SELECT TOP 1 #A.ParentID FROM #A) ParentID,Amount FROM #A
      

      使用 EXCEPT 将避免 #A 中已经存在的行,我们将获得用于插入查询的唯一行。

      更多示例数据请参考 DB Fiddle:https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=de51af7d0e1e7ff0407c445a301c5560

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-26
        • 1970-01-01
        • 1970-01-01
        • 2015-12-01
        • 1970-01-01
        • 2017-12-14
        • 1970-01-01
        相关资源
        最近更新 更多