根据序列中另一列的 ID 引用列

Referencing column depending on Ids of another column in sequence

我正在尝试更新(引用)一个 table 的列 (oid) 与另一个 table 的列的 OID 具有特定条件。

示例:

Customer Table :
------------------
CID  name   oid
-------------------
1  abc     null
2  abc     null
3  abc     null
4  xyz     null
--------------------

Order Table
--------------
OID  name
--------------
10   abc
11   abc
12   abc
13   xyz
--------------

输出应该是:

Customer Table :
------------------
CID  name   oid
-------------------
1    abc     10
2    abc     11
3    abc     12
4    xyz     13
--------------------

我试过以下方法

UPDATE customer as c, order as o
   SET c.oid = o.OID
   WHERE c.name = o.name;
-----------------------------
update customer INNER JOIN order on customer.name=Order.name
SET customer.oid=Order.OID
where customer.oid IS null;

但是客户table正在更新如下

Customer Table :
------------------
CID  name   oid
-------------------
1    abc     10
2    abc     10
3    abc     10
4    xyz     13
--------------------

这个做起来很复杂。您需要为每个值分配一个计数器变量——这在 update 语句中有点痛苦。但是这样的事情应该有效:

update customer c join
       (select c.*,
               (@rn := if(@n = name, @rn + 1,
                          if(@n := name, 1, 1)
                         )
               ) as rn
        from customer c cross join
             (select @n := '', @rn := 0) params
        order by name, cid
       ) cc
       on c.cid = cc.cid join
       (select o.*,
               (@rno := if(@no = name, @rno + 1,
                           if(@no := name, 1, 1)
                          )
               ) as rn
        from orders o cross join
             (select @no := ', @rno := 0) params
       ) o
       on c.name = o.name and c.rn = o.rn
    set c.oid = o.oid;

想法是为 Customer table 和 Order table.

中的每个条目分配一个行号

因此,当在这两个 table 之间创建 inner join 时,您现在有两个条件(而之前它是一个,即唯一的名称)。

一个条件是name,另一个是row_number

您可以使用此查询:

UPDATE Customer CT
INNER JOIN (
    SELECT
        customerTable.CID,
        orderTable.OID FROM 
        (
            SELECT
                *, 
                @rn1 := @rn1 + 1 AS row_number
            FROM
                Customer C
            CROSS JOIN (SELECT @rn1 := 0) var
            ORDER BY CID
        ) AS customerTable
    INNER JOIN (
        SELECT
            *, 
            @rn2 := @rn2 + 1 AS row_number
        FROM
            `Order` O
        CROSS JOIN (SELECT @rn2 := 0) var
        ORDER BY OID
    ) AS orderTable ON customerTable. NAME = orderTable. NAME
    AND customerTable.row_number = orderTable.row_number
) AS combinedTable ON CT.CID = combinedTable.CID
SET CT.oid = combinedTable.OID

注意: 因为在匹配 name 时加入这两个 table 不足以满足您的需求。这就是为什么除了匹配名称之外,还要为每一行分配一个 row_number(在 CustomerOrder table 中)。然后在这两个 table 之间进行内部连接s 匹配 namerow number。因此,您限制一个条目与另一个 table 的其他条目多次连接。


测试方案和数据:

无法添加 sql fiddle

DROP TABLE IF EXISTS `customer`;
CREATE TABLE `customer` (
  `CID` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `oid` int(11) DEFAULT NULL,
  PRIMARY KEY (`CID`)
);
INSERT INTO `customer` VALUES ('1', 'abc', null);
INSERT INTO `customer` VALUES ('2', 'abc', null);
INSERT INTO `customer` VALUES ('3', 'abc', null);
INSERT INTO `customer` VALUES ('4', 'xyz', null);

DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
  `OID` int(11) NOT NULL,
  `name` varchar(100) NOT NULL
);
INSERT INTO `order` VALUES ('10', 'abc');
INSERT INTO `order` VALUES ('11', 'abc');
INSERT INTO `order` VALUES ('12', 'abc');
INSERT INTO `order` VALUES ('13', 'xyz');

现在看看,Customer table 长什么样子:

SELECT
*
FROM Customer;

输出:

CID name  oid
1   abc   10
2   abc   11
3   abc   12
4   xyz   13