【问题标题】:SQL Get values from other tables before Insert Into query commandSQL 在插入查询命令之前从其他表中获取值
【发布时间】:2018-05-10 17:20:52
【问题描述】:

我想创建一个查询,允许我在将 ID 的名称添加到查询调用的所需表之前查找另一个表中显示的数字。

一个例子:

表1

ID   |name   |nameID |network |...
----------------------------------
5    |Bob    |4      |NPOW    |...
6    |Billy  |8      |BGER    |...

表2

ID   |name   |nameID |network |...
----------------------------------
3    |Stan   |2      |ERFDT   |...

表3

ID   |name   |nameID |network |...
----------------------------------
3    |Steve  |3      |FRVS    |...

Table4(我在下面插入新行的表)

ID   |name   |nameID |network |...
----------------------------------

在我的页面上,这些是我需要添加到上面 table4 的新值:

Name   |ID |network |...
------------------------
Nick   |4  |RFGH    |...
Tony   |3  |ESLO    |...
James  |2  |HUII    |...
Rusty  |3  |ERNM    |...

现在我想做的是查看哪一列 ID 等于 X 并将该名称放入 Table4

这样做 table4 的结果应该如下所示插入后

ID   |name   |nameFromID |network |...
--------------------------------------
1    |Nick   |Bob        |RFGH    |...
2    |Tony   |Steve      |ESLO    |...
3    |James  |Stan       |HUII    |...
4    |Rusty  |Steve      |ERNM    |...

那么 INSERT INTO Table4 查询 会是什么样子?

【问题讨论】:

  • nameID 在表 1-3 中是否唯一?像 3 这样的 nameID 可以在多个表中吗?
  • 是的,@dfundako
  • 那你想做什么?

标签: sql sql-server tsql sql-server-2016


【解决方案1】:

您可以使用视图、一些连接和临时表或其他带有会话范围的临时表来执行此操作。这是一个临时表方法。

将所有不同的表合并到一个可查询的表单中的视图:

CREATE VIEW vAllNames
AS
SELECT [Name], NameID FROM Table1 UNION
SELECT [Name], NameID FROM Table2 UNION
SELECT [Name], NameID FROM Table3

以上假设NameId不能在这些表中重复,所以我使用UNION而不是UNION ALL。否则,当 id 成功匹配多个表时,您需要告诉我们您希望如何解析名称。您是否希望将多条记录插入到表 4 中,只有第一个匹配项、某种连接等。

临时表,因此我们可以从中选择插入的内容,除非您想一次插入一个(您也可以使用会话范围的持久表或类似的东西来执行此操作):

CREATE TABLE #TempDataToInsert
(
    [Name] NVARCHAR(256),
    ID INT,
    network CHAR(4)
)

创建这些后,您可以将页面中的数据直接插入TempDataToInsert。一旦您的数据在那里上演,您就可以运行最终的insert into

INSERT INTO Table4
    ([Name], nameFromID, network) -- Assumes ID is an identity column
SELECT
    tempData.[Name], allNames.[Name], tempData.network
FROM
    #TempDataToInsert tempData
    LEFT OUTER JOIN vAllNames allNames ON tempData.ID = allNames.NameID -- assumes no match is still valid for insertions

之后您需要清理临时表,我对您的架构做了一些假设,但这应该会为您指明正确的方向。

【讨论】:

    【解决方案2】:
    CREATE TABLE #Temp0
    (
        ID INT,
        [Name] VARCHAR(100),
        NameId INT,
        Network VARCHAR(100)
    );
    
    INSERT INTO #Temp0
    (
        ID,
        Name,
        NameId,
        Network
    )
    VALUES
    (5, 'Bob', 4, 'NPOW'),
    (6, 'Billy', 8, 'BGER');
    
    CREATE TABLE #Temp1
    (
        ID INT,
        [Name] VARCHAR(100),
        NameId INT,
        Network VARCHAR(100)
    );
    INSERT INTO #Temp1
    (
        ID,
        Name,
        NameId,
        Network
    )
    VALUES
    (3, 'Stan', 2, 'ERFDT');
    CREATE TABLE #Temp2
    (
        ID INT,
        [Name] VARCHAR(100),
        NameId INT,
        Network VARCHAR(100)
    );
    INSERT INTO #Temp2
    (
        ID,
        Name,
        NameId,
        Network
    )
    VALUES
    (3, 'Steve', 3, 'FRVS');
    SELECT *
    INTO #Temp
    FROM
    (
        SELECT [Name],
               NameId
        FROM #Temp0
        UNION
        SELECT [Name],
               NameId
        FROM #Temp1
        UNION
        SELECT [Name],
               NameId
        FROM #Temp2
    ) AS Temp;
    
    
    
    CREATE TABLE #Temp3
    (
        [Name] VARCHAR(100),
        Id INT,
        Network VARCHAR(100)
    );
    
    INSERT INTO #Temp3
    (
        Name,
        Id,
        Network
    )
    VALUES
    ('Nick', 4, 'RFGH'),
    ('Tony', 3, 'ESLO'),
    ('James', 2, 'HUII'),
    ('RUSTY', 3, 'ERNM');
    
    
    CREATE TABLE #Table4
    (
        ID INT IDENTITY(1, 1),
        [Name] VARCHAR(100),
        NameFormId VARCHAR(100),
        Network VARCHAR(100)
    );
    
    INSERT INTO #Table4
    SELECT T2.Name,
           T1.Name,
           T2.Network
    FROM #Temp T1
        JOIN #Temp3 T2
            ON T1.NameId = T2.Id;
    
    SELECT *
    FROM #Table4;
    

    【讨论】:

      【解决方案3】:

      以下代码演示了如何在表之间匹配NameId 上的数据。它假定添加的Names 是唯一的。如果输入表之间有多个NameId 匹配,则优先考虑最早的匹配。单个输入表中的多个NameId 匹配优先考虑最低的Id

      -- Sample data.
      declare @Table1 as Table ( Id Int, Name VarChar(10), NameId Int, Network VarChar(10) );
      insert into @Table1 ( Id, Name, NameId, Network ) values
        ( 5, 'Bob', 4, 'NPOW' ), ( 6, 'Billy', 8, 'BGER' );
      select * from @Table1;
      
      declare @Table2 as Table ( Id Int, Name VarChar(10), NameId Int, Network VarChar(10) );
      insert into @Table2( Id, Name, NameId, Network ) values
        ( 3, 'Stan', 2, 'ERFDT' );
      select * from @Table2;
      
      declare @Table3 as Table ( Id Int, Name VarChar(10), NameId Int, Network VarChar(10) );
      insert into @Table3 ( Id, Name, NameId, Network ) values
        ( 3, 'Steve', 3, 'FRVS' ),
        ( 4, 'Steven', 3, 'FRVS' ), -- Note duplicate   NameId   value.
        ( 9, 'Stanley', 2, 'VOOT' ); -- Note duplicate   NameId   value.
      select * from @Table3;
      
      declare @ValuesToAdd as Table ( Name VarChar(10), NameId Int, Network VarChar(10) );
      insert into @ValuesToAdd ( Name, NameId, Network ) values
        ( 'Nick', 4, 'RFGH' ), ( 'Tony', 3, 'ESLO' ),
        ( 'James', 2, 'HUII' ), ( 'Rusty', 3, 'ERNM' );
      select * from @ValuesToAdd;
      
      -- Process the data.
      declare @Table4 as Table ( Id Int Identity, Name VarChar(10), NameId Int,
        NameFromId VarChar(10), Network VarChar(10) );
      -- Demonstrate the matching.
      select Name, NameId, NameFromId, Network
        from (
          select VTA.Name, VTA.NameId, N.Name as NameFromId, VTA.Network,
            Row_Number() over ( partition by VTA.Name order by NameRank, Id ) as RN
            from @ValuesToAdd as VTA inner join ( -- Use   left outer join   if there might not be a match on   NameId .
              select Id, Name, NameId, 1 as NameRank from @Table1 union all
              select Id, Name, NameId, 2 from @Table2 union all
              select Id, Name, NameId, 3 from @Table3 ) as N on N.NameId = VTA.NameId ) as PH
        --where RN = 1; -- Pick the match from the earliest table.
      -- Insert the results.
      insert into @Table4
        select Name, NameId, NameFromId, Network
          from (
            select VTA.Name, VTA.NameId, N.Name as NameFromId, VTA.Network,
              Row_Number() over ( partition by VTA.Name order by NameRank, Id ) as RN
              from @ValuesToAdd as VTA inner join ( -- Use   left outer join   if there might not be a match on   NameId .
                select Id, Name, NameId, 1 as NameRank from @Table1 union all
                select Id, Name, NameId, 2 from @Table2 union all
                select Id, Name, NameId, 3 from @Table3 ) as N on N.NameId = VTA.NameId ) as PH
          where RN = 1; -- Pick the match from the earliest table.
      select * from @Table4;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-03
        • 1970-01-01
        • 2023-01-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多