插入具有多对多关系的第三个表

时间:2016-06-21 18:57:51

标签: sql postgresql

我有3个表,一个有库存ID,一个有用户ID,第三个有库存ID,用户ID和用户库存ID。

表1:

 | stockID 
 | 10001
 | 10002 
 | 10003 
 | 10004 

表2:

|userID 
| 11000
| 11001
| 11002

表3:

|stockID |userID  |userByStock 
| 10001  | 11000    0001
| 10002  | 11000    0002
| 10003  | 11000    0003
| 10004  | 11000    0004
| 10001  | 11001    0005

在表3中,我想插入并让所有用户拥有所有库存ID,并且userByStock总是递增1。

基本上,我需要获取表3中尚不存在的所有库存ID,并将它们添加到每个用户,并将userByStock列增加1.

我尝试过类似的事情:

INSERT INTO table3 select table1.stockID FROM table1 WHERE table1.stockID NOT IN (SELECT stockID FROM table 3);

但我被困了

编辑:我还需要从table2中获取所有尚未在table3中的userID并将它们插入到table3中

4 个答案:

答案 0 :(得分:1)

WITH cteAllPossibleCombinations AS (

    SELECT
       StockId
       ,UserId
    FROM
       Table1
       CROSS JOIN Table2
)

, cteMaxUserByStock AS (
    SELECT MAX(CAST(userByStock AS INT)) AS MaxUserByStock
    FROM
       Table3
)

INSERT INTO Table3 (StockId, UserId)
SELECT StockId, UserId, userByStock = m.MaxUserByStock + ROW_NUMBER() OVER (PARTITION BY 1)
FROM
    Table3 t
    LEFT JOIN cteAllPossibleCombinations x
    ON t.StockId = x.StockId
    AND t.UserId = x.UserId
    CROSS JOIN cteMaxUserByStock m
WHERE
    x.StockId IS NULL;

我想如果你可以修改表3并将其设置为执行身份/自动增量列,那么如果不是只将最大值与row_number结合起来,你应该很高兴。您也可以使用与WHERE()IN SELECT答案相同的技术。

答案 1 :(得分:0)

您可以对表格a使用选择,而不是

中的耦合值
    INSERT INTO table3  select table1.stockID, table2.userID 
    FROM table1, table2 
    WHERE (table1.stockID, table2.userID) NOT IN (SELECT stockID, userID FROM table 3);

答案 2 :(得分:0)

    create table table3 ( stockId smallint unsigned not null, userId smallint unsigned not null, userByStock smallint zerofill unsigned auto_increment primary key);

    insert into table3 (stockId, userId) select table1.stockId, table2.userId from table1 cross join table2;


    stockId | userId | userByStock |
    +---------+--------+-------------+
    |       1 |      1 |       00001 |
    |       2 |      1 |       00002 |
    |       1 |      2 |       00003 |
    |       2 |      2 |       00004 |
    |       1 |      3 |       00005 |
    |       2 |      3 |       00006 |
    +---------+--------+-------------+

但是......如果你不能添加auto_increment ......

   set @m:=(select max(userByStock) from table3); insert into table3 (stockId, userId, userByStock) select table1.stockId, table2.userId, (@m := @m + 1) from table1 cross join table2;

并且......完整的解决方案将是:

   set @m:=(select max(userByStock) from table3); insert into table3 (stockId, userId, userByStock) select table1.stockId, table2.userId, (@m := @m + 1) from table1 cross join table2 where not exists(select * from table3 as t3 where t3.stockId = table1.stockId and t3.userId = table2.userId);

答案 3 :(得分:0)

我会考虑简单地执行INSERT IGNORE,假设您在连接表上的stockID和userID字段中有唯一索引。

INSERT IGNORE INTO table3 (stockID, userID)
SELECT table1.stockID, table2.userID
FROM table1 CROSS JOIN table2

这会尝试将table1和table2的笛卡尔(交叉)连接插入到表3中,忽略stockID和userID的唯一索引已经存在的所有行。

假设您的userByStock字段是自动增量字段,插入该字段的值将自动递增。

当您认为需要添加到table3的行数表示table1和table2中行组合的显着百分比时,这可能是一个很好的解决方案。如果你只有一行或两行要添加到表3中,而table3有很多行,那么这个解决方案可能不会像专门识别必要的插入那样最优,就像你本质上会做一堆插入一样忽略。