【问题标题】:How to populate a column from another column?如何从另一列填充一列?
【发布时间】:2013-04-25 08:06:19
【问题描述】:

我有两个表,分别名为 ComputerReportSoftwareReport。在第一个表中,我添加了一个名为 SFID 的整数列。我使用此列在第一个表和第二个表之间建立链接。第二个表也有一个名为SFID的列,这也是表的主键。

我想要的是将表SoftwareReport 中的SFID 列填充到ComputerReportSFID 列中。在下图中,您可以看到两个表,但 ComputerReport 中的 SFID 列是 NULL

如何将 SoftwareReport 表中的 ID 填充到 ComputerReportSFID 列中,并且应该只添加不存在的程序名称。

这是图片的链接:http://i33.tinypic.com/2usewr8.jpg

谢谢,

杰米

【问题讨论】:

  • 你的逻辑一点都不清楚。两个表之间的链接是什么,例如你在ComputerReport 的第一行是1, 'JAMIE-HP', 'JAMIE-HP/Jamie', '2013-04-24 14:21:09.000',我看不出这应该是什么SFID?如果没有公共列(除了 NULL SFID),就无法执行更新。
  • 我在它们之间建立了一个链接以使用一个列,例如 (WHERE ComputerReport.SFID = SoftwareReport.SFID)。但我希望将 SoftwareReport 中的 SFID 放入 ComputerReport SFID 列。因此,当我保存一个带有程序名称的新列表时,它会首先检查名称。 SQL 将只添加新的程序名称。当程序名称已经存在于该列表中时,他只获取 SFID 并将其放入 ComputerReport SFID。但我不知道该怎么做。
  • 好的,但是SFID 的第一行应该是什么ComputerReport,为什么?理解这一点是创建更新语句以及添加新程序名称的逻辑的关键。
  • 你需要能够用英文的单词、句子、段落而不是图片来表达你想要表达的东西。
  • 您还需要进一步解释每个表是如何预先填充的情况,以便我们了解您为什么要这样做。

标签: c# sql wpf visual-studio-2010


【解决方案1】:

如果您的逻辑只是用软件报告表中的第一项更新第一台计算机报告,第二次更新第二次,第三次更新第三次等等,那么这对您有用:

WITH CR AS
(   SELECT  CRID, Name, SFID, rn = ROW_NUMBER() OVER(ORDER BY CRID) 
    FROM    ComputerReport
), SF AS
(   SELECT  SFID, Name, rn = ROW_NUMBER() OVER(ORDER BY SFID)
    FROM    SoftwareReport
)
MERGE INTO CR
USING SF
    ON sf.rn = cr.rn
WHEN MATCHED THEN 
    UPDATE SET SFID = sf.SFID
WHEN NOT MATCHED THEN
    INSERT (Name, SFID) VALUES (sf.Name, sf.sfID);

如果 SFID,这只是用软件表中的相应行更新计算机报告表。如果软件报告表中还有其他行,它将在计算机报告表中添加一个新行,以便行数匹配

Example on SQL Fiddle

【讨论】:

  • 谢谢 :) 但是这和我在这张照片中问的一样吗? i36.tinypic.com/2ly3eko.png 就是这样。不多。但是当我在另一台计算机或笔记本电脑上进行扫描并且某些程序名称相同时,他必须获取该 SFID 并将其放入 ComputeReport(最后一列称为 SFID)。
  • 这是尽可能接近你想要的,因为围绕更新的规则似乎几乎不存在。如果没有ComputerReport 中的 SFID 列,就无法将CRIDSFID 链接起来。据我所知,没有理由CRID = 1 的行应该有SFID = 1,除了它们都是各自表中的第一行。如果您可以提供一个实际的算法来执行更新,那么我可能会提出一个更适合的答案,但目前根据表格中的位置进行更新是我能提供的最好的。
  • 如果您不想在ComputerReport 中插入新行,那么只需删除MERGE 语句的WHEN NOT MATCHED 部分。
  • GarethD,我正在使用存储过程,但是如何将该代码插入到我的存储过程中?因为在我的 sp 中我使用“INSERT INTO”。但那应该是“合并”?
  • 是的,您可以在存储过程中使用MERGE,只要确保您事先使用; 终止语句(虽然实际上您应该终止每个带有分号的声明,这样做的原因在Aaron Bertrand's blog中提到
【解决方案2】:

通常,您应该在 ComputerReport 中插入一行,其中已确定正确的 SFID,而不是更新已插入的行。

INSERT INTO ComputerReport
(SFID, CrComputerName, CrLastUpdatedBy) -- add other columns as neeeded 
SELECT SFID, 'JAMI-HP', 'JAMIE-HP\JAMIE'
FROM SoftwareReport

您可以截断ComputerReport 表并执行上述插入,如果该表不包含任何有价值的内容。

否则,你需要一个光标跟随每个表,并根据光标位置第一个表中SFID的值在第二个表中设置SFID光标位置。

在理想情况下,你刚刚创建了行,两个表之间没有间隙,并且它们都包含相同数量的行,所以我们可以简单地写:

UPDATE ComputerReport 
SET SFID = CRID

但在一般情况下,我们必须求助于更复杂的脚本:

DECLARE @sfid, @crid

DECLARE sfcursor READONLY
FOR SELECT SFID
    FROM SoftwareReport
    WHERE SFName IS NOT NULL
    ORDER BY SFID ASC;
DECLARE crcursor
FOR SELECT CRID
    FROM  ComputerReport
    -- WHERE SFID IS NULL
    ORDER BY CRID ASC
FOR UPDATE SFID;

OPEN sfcursor;
OPEN crcursor;

FETCH NEXT FROM sfcursor INTO @sfid;
FETCH NEXT FROM crcursor INTO @crid;

-- update for each rows until we reach the end of either cursor
WHILE @@FETCH_STATUS = 0
     BEGIN
     UPDATE crcursor SET SFID = @sfid;
     FETCH NEXT FROM sfcursor INTO @sfid
     FETCH NEXT FROM crcursor INTO @crid
     END

-- if there are remaining rows in sfcursor, insert new rows in ComputerReport

FETCH RELATIVE 0 FROM sfcursor INTO @sfid
WHILE @@FETCH_STATUS = 0
    BEGIN
    INSERT INTO ComputerReport (SFID) -- you should add the other columns here as needed
    VALUES (@sfid);
    FETCH NEXT FROM sfcursor INTO @sfid
    END

CLOSE crcursor
CLOSE sfcursor
DEALLOCATE sfcursor
DEALLOCATE crcursor

如脚本中所示,您应该修改 INSERT 查询,以使用所需的列和值来获取 ComputerReport 中的额外行。

请注意,与常规(基于集合)查询相比,基于游标的脚本速度较慢。 参考资料:

【讨论】:

  • 谢谢,我不是 SQL 专家。这就是我要的。见 --> i36.tinypic.com/2ly3eko.png
  • 当然,我也不是 SQL99 专家。我建议对另一个答案的MERGE 查询执行我的脚本尝试执行的操作,并且是您想要的
  • 顺便说一句,这是我的第一个 tsql 脚本,所以如果它不是惯用的甚至包含错误,请不要感到惊讶。
  • 感谢您的帮助! :)
【解决方案3】:

如果我得到了您想要正确实现的目标,您必须将 CRID 添加到 SoftwareReport 表中并从 ComputerReport 中删除 SFID。

然后,当您添加新软件报告时,您将使用上次报告中的 CRID...

这是有效的,你想实现这个: 每次您运行检查时,它都会创建新的计算机报告,并在发生连接时将新软件添加到通用列表中,换句话说,哪个计算机报告报告了新软件。

【讨论】:

    【解决方案4】:

    我真的不太了解问题。很抱歉,如果我的回答不相关。据我了解,您想链接计算机和软件。为此,您需要多对多关系。因为一个软件可以在多台计算机上,而一台计算机可以有很多软件。为了实现这一点,您需要另一个由两列组成的表: 计算机软件(CID、SFID)。 例如,如果 id 为 1 的计算机有 id 为 2 和 3 的软件,则应插入 (1, 2) 和 (1, 3) 到 ComputerSoftware 表。

    【讨论】:

    • 是的,我知道你在说什么。我也做个参考。 ALTER TABLE ComputerReport ADD FOREIGN KEY (SFID) REFERENCES SoftwareReport(SFID) 因为程序比计算机多。
    • 不,我的意思是您需要另一个表作为 ComputerSoftware(CID、SFID),它将计算机和软件结合在一起。
    • 啊,我为此创建了一个视图。是这个意思吗?
    • 没有。你不想把电脑和软件联系起来吗?例如,假设在 Computers 表中,您有类似 [(C_ID, C_NAME)]: (1, "FirstComputer"), (2, "SecondComputer") 的计算机。您在软件表 [(SF_ID, SF_NAME)] 中有以下数据:(1, "FirstProgram"), (2, "SecondProgram")。现在在你的表格中,你怎么能说 FirstComputer 有 SecondProgram 而 SecondComputer 有 FirstProgram 和 SecondProgram?
    • 这应该是结果然后 Adil Mammadov, ComputerReport TABLE: 1, "FirstComputer", "LastUpdatedBy", "LastUpdatedOn", 12 2, "FirstComputer", "LastUpdatedBy", "LastUpdatedOn", 6 3, "FirstComputer", "LastUpdatedBy", "LastUpdatedOn", 2 --------- SoftwareReport TABLE: 1, "Adobe Reader" 2, "Messenger" ... 6, "Skype" ... 12 , "BitTorrent" ... 所以一台名为 "FirstComputer" 的计算机安装了以下程序: 2 = Messenger 6 = Skype 12 = BitTorrent 这应该是结果。我希望你现在能理解我
    猜你喜欢
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 2012-11-25
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 1970-01-01
    相关资源
    最近更新 更多