【问题标题】:How to make all rows in a table identical which the exception of 1 field?如何使表中的所有行都相同,除了 1 个字段?
【发布时间】:2017-04-17 02:20:22
【问题描述】:

我正在努力让所有用户都拥有相同的项目,因为我正在对我的应用进行实验并且需要对展平数据进行实验控制。

我在上次尝试中使用了以下 SQL 语句:

insert into has (email,id,qty,price,item_info,image)  
select 'b@localhost.com',id,qty,price,item_info,image  
from 
(  
  select * from has  
  where email != 'b@localhost.com'  
) as o  
where o.id not in
(
 select id from has
 where email = 'b@localhost.com'
);

这应该将“b@localhost.com”尚未拥有但其他用户拥有的所有项目添加到“b@localhost.com”的库存中。 (“有”表)

但是,我收到以下错误:
该语句已中止,因为它会导致唯一或主键约束或唯一索引中的重复键值

我了解此错误的含义,但我不明白为什么会发生。我的语句插入了该电子邮件尚未包含的所有记录,因此不应有任何重复的 id/email 对。

数据库结构如下图,圆圈是属性,正方形是表格,菱形是关系集。 HAS 表是在 USER_ACCOUNT 和 ITEM 上设置的关系,其中主键分别是 email 和 id。

【问题讨论】:

  • 澄清一下,您希望每个用户都拥有与其他用户相同的项目吗?
  • 是的,物品由'id'属性表示。
  • 我认为我的策略太复杂了,我应该将所有内容复制到临时表中,然后为 4 个用户执行 4 次插入。
  • has中的主键字段是什么?
  • HAS 是一个关系集,所以它的主键是它所连接的表的主键。即:USER_ACCOUNT 的“email”和ITEM 的“id”。

标签: sql derby


【解决方案1】:

请尝试以下...

INSERT INTO has ( email,
                  id,
                  qty,
                  price,
                  item_info,
                  image )
SELECT a.email,
       b.id,
       a.qty,
       a.price,
       a.item_info,
       a.image
FROM has a
CROSS JOIN has b
JOIN
(
    SELECT email,
           id
    FROM has
) c ON a.email = c.email AND
       b.id <> c.id;

CROSS JOINhas 的每一行的副本附加到has 的每一行。有关CROSS JOIN 的更多信息,请参阅http://www.w3resource.com/sql/joins/cross-join.php

结果数据集的每一行将有两个id 字段、两个email 字段、两个qty 字段等。通过给has 的每个实例一个别名,我们创建字段a.id、@ 987654335@、a.email

然后,我们将“旧”email 地址和“新”id 的每个组合与现有email / id 组合的列表进行比较,并用新的id 替换旧的值插入旧值一进has

如果您有任何问题或cmets,请随时发表相应的评论。

进一步阅读

http://www.w3resource.com/sql/joins/cross-join.php 了解有关CROSS JOIN 的更多信息

https://www.w3schools.com/sql/sql_in.asp 了解有关WHEREIN 运算符的更多信息

https://www.w3schools.com/sql/sql_groupby.asp 了解更多关于GROUP BY的信息

【讨论】:

  • 我仍然遇到同样的错误,但感谢您的尝试。
  • 我不确定它为什么不起作用。我仍然得到同样的错误。它适用于我尝试的第一个用户,然后在其他用户上不起作用。
  • 我应该问这里的 a , b, c 是什么意思?您是在暗示电子邮件应该替换那些部分吗?
  • 解释中。
  • 也许这是因为我正在使用 Derby,但我遇到了语法错误,(我的印象是 Derby 基本上是 SQL)。它说一些连接之间的逗号是不正确的语法
【解决方案2】:

我认为这里的问题不是代码试图插入已经存在的东西,而是它试图插入多个具有相同 PK 的东西。代替对我的评论的回应,这是解决此问题的一种方法:

INSERT INTO has (email,id,qty,price,item_info,image)  
SELECT
    'b@localhost.com',
     source.id,
     source.qty,
     source.price,
     source.item_info,
     source.image  
FROM 
    (  
    SELECT email, id, qyt, price, item_info, image FROM has  
    ) as source
    JOIN
    (
    SELECT min(email) as min_email, id FROM has GROUP BY by id)
    ) as filter ON
     filter.min_email = source.email
WHERE
    source.id not in
    (
    SELECT id from has WHERE email = 'b@localhost.com'
    );

与原始代码的主要区别在于我对子查询的额外连接,我将其别名为filter。这将限制您从每个 id 的单个 email 插入 has 详细信息。还有其他方法可以做到这一点,但我认为这将是获得德比支持的安全赌注。

我从source 子查询中删除了WHERE 子句,因为它由最终的WHERE 处理。

【讨论】:

    猜你喜欢
    • 2015-10-18
    • 2011-12-14
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 1970-01-01
    • 2017-08-02
    相关资源
    最近更新 更多