【问题标题】:How to make a link between what was inserted and where it came from如何在插入的内容和它的来源之间建立联系
【发布时间】:2016-08-27 20:52:15
【问题描述】:

我正在插入一个类似的表格

项目(itemId, name),其中 id 是一个身份。

从这样的表中

RawData(名称、描述、其他信息),其中可能有多个名称。比如“A”出现3次,就说它看起来像这样

A,Desc1,x
A,Desc1,y
A,Desc2,z
B,Desc1,x

插入项目后,我得到 3 个“A”条目,比如说

1,A
2,A
3,A
4,B

现在我想插入一个名为 描述(DescriptionId、ItemId、描述)

我无法准确提供填充 itemId 1、2、3 的 SQL,因为将 Items 连接回 RawData 不提供 1:1

我想做

INSERT INTO Descriptions
SELECT ItemId, description
FROM RawData R
INNER JOIN Items I ON I.name = R.name

我想要加入它并让它像(最后两列是项目)

A,Desc1,x,1,A
A,Desc1,y,2,A
A,Desc2,z,3,A
B,Desc1,x,4,B

我得到的是

A,Desc1,x,1,A
A,Desc1,x,1,A
A,Desc1,x,1,A
A,Desc1,y,2,A
A,Desc1,y,2,A
A,Desc1,y,2,A
A,Desc2,z,3,A
A,Desc2,z,3,A
A,Desc2,z,3,A
B,Desc1,x,4,B

我想到的一个解决方案是向 RawData 添加一个标识,然后在我插入 Items 时将其包含在内,以帮助我将表链接回它们的原样。然后当我完成删除该列。但这似乎是一种非常老套的方式。

我能想到的另一个解决方案是 SQL 之类的

INSERT INTO Descriptions
SELECT DISTINCT ItemId, description
FROM RawData R
INNER JOIN Items I ON I.name = R.name

但这在我的真实示例中不起作用。我从 RawData 中的 200 个项目开始,在加入后以 215 个项目结束,所以显然没有发生 1:1

我正在寻找解决问题的通用方法。没有多少解决方案适用于这个特定示例(这就是示例如此基础的原因)

【问题讨论】:

  • 那么,首先,三个不同的项目怎么可能有相同的名字呢?你的问题....当您执行连接时,这种违反您用作键的唯一性的行为会导致结果集中出现笛卡尔积
  • 是的,这就是数据的本质。它们是 4 个独特的项目,但 3 个具有相同的名称。
  • 那么数据损坏了,或者你没有正确理解它。如果三个不同的项目可能具有相同的属性值,则该属性不能用作键值来查找和引用表中的单行。你还不清楚吗?
  • 即如果有 5 个名为 bob smith 的人,您将无法识别和定位单个 bob smith。
  • 数据未损坏。我知道我正在做的是尝试使用一个不唯一的密钥,这就是它找到多个匹配项的原因。我所追求的是一个解决方案来达到我的最终结果。不包含临时修改 Items 表以添加唯一键以加入的想法和方法

标签: sql-server join cross-reference


【解决方案1】:

由于您的目标是在导入时使用新填充的Items 填充与原始数据匹配的Descriptions 表,因此您可以在Items 表中添加一列,该列将唯一标识一行并在填充@ 后将其删除987654325@.

假设在您的情况下,唯一性将在 (name, description, otherinfo)

SQL Fiddle 向您展示它是如何工作的。

创建表格

CREATE TABLE items(itemid int primary key auto_increment, name text);
CREATE TABLE descriptions(descriptionid int primary key auto_increment, itemid int, description text);
CREATE TABLE rawdata(name text, description text, otherinfo text);

添加临时列

ALTER TABLE items ADD COLUMN tmp_unique text;

填充项目

INSERT INTO items (name, tmp_unique)
  SELECT name, concat(description, '#', otherinfo)
  FROM rawdata;

填充描述

INSERT INTO descriptions (itemid, description)
  SELECT itemid, description
  FROM rawdata r
  INNER JOIN items i ON
    r.name = i.name
    AND concat(r.description, '#', r.otherinfo) = i.tmp_unique;

删除临时列

ALTER TABLE items DROP COLUMN tmp_unique;

注意:如果您关心速度,那么在您的情况下,您可以创建两个独特的列,并分别从 rawdata 中放置描述和其他信息,然后在填充描述时将这两个列加入。 p>

【讨论】:

  • 这可能是最好的方法,虽然我很谨慎,因为在我插入之前 Items 表将有 1000 条记录。
  • 祝你好运,使用不同的方法。我的朋友,循环会慢得多:)
【解决方案2】:

刚想到这一点,我想将其添加为潜在的解决方案。

将身份列“ID”添加到 RawData。

在插入项目之前:

DECLARE @StartId INT = ( SELECT IDENT_CURRENT('dbo.Items'));

然后使用RawData的@StartId + IDItems进行身份INSERT;

以后就可以使用了

SELECT @StartId+ID as ItemId, description
FROM RawData R

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    • 2011-04-06
    • 2023-03-18
    相关资源
    最近更新 更多