使用另一个表中的列动态更新表

时间:2017-04-17 19:32:17

标签: sql salesforce

我有一个像这样的表客户:

CREATE TABLE tbl_customer (
  id INTEGER,
  name VARCHAR(16),
  voucher VARCHAR(16)
);

和这样的凭证表:

CREATE TABLE tbl_voucher (
  id INTEGER,
  code VARCHAR(16)
);

现在假设customer表始终包含填写了id和name的行,但是需要定期从tbl_voucher表插入凭证。

重要提示:每张优惠券只能分配给一个特定客户(即必须是唯一的)

我写了一个这样的查询:

UPDATE tbl_customer
SET voucher = (
    SELECT code
    FROM tbl_voucher
    WHERE code NOT IN (
        SELECT voucher
        FROM tbl_customer
        WHERE voucher IS NOT NULL
    )
    LIMIT 1
)
WHERE voucher IS NULL;

然而,这不能按预期工作,因为查找未使用的凭证的部分会执行一次,然后凭证会应用于每个客户。

关于如何在不使用循环等编程结构的情况下解决这个问题的任何想法?

此外,一些示例数据让您可以想象我想要发生的事情:

INSERT INTO tbl_customer VALUES (1, 'Sara', 'ABC');
INSERT INTO tbl_customer VALUES (1, 'Simon', 'DEF');
INSERT INTO tbl_customer VALUES (1, 'Andy', NULL);
INSERT INTO tbl_customer VALUES (1, 'Alice', NULL);

INSERT INTO tbl_voucher VALUES (1, 'ABC');
INSERT INTO tbl_voucher VALUES (2, 'LOL');
INSERT INTO tbl_voucher VALUES (3, 'ZZZ');
INSERT INTO tbl_voucher VALUES (4, 'BBB');
INSERT INTO tbl_voucher VALUES (5, 'CCC');

执行完所需的查询后,我希望Andy能够获得凭证LOL,而Alice应该获得ZZZ

1 个答案:

答案 0 :(得分:2)

我猜这是MySQL。答案是,这是一种痛苦。以下内容分配select

中的值
select c.*, v.voucher
from (select c.*, (@rnc := @rnc + 1) as rn
      from tbl_customer c cross join
           (select @rnc := 0) params
      where c.voucher is null
     ) c join
     (select v.*, (@rnv := @rnv + 1) as rn
      from tbl_vouchers v cross join
           (select @rnv := 0) params
      where not exists (select 1 from tbl_customers c where c.voucher = v.voucher)
     ) v
     on c.rn = v.rn;

您现在可以将其用于update

update tbl_customer c join 
       (select c.*, v.voucher
        from (select c.*, (@rnc := @rnc + 1) as rn
              from tbl_customer c cross join
                   (select @rnc := 0) params
              where c.voucher is null
             ) c join
             (select v.*, (@rnv := @rnv + 1) as rn
              from tbl_vouchers v cross join
                   (select @rnv := 0) params
              where not exists (select 1 from tbl_customers c where c.voucher = v.voucher)
             ) v
             on c.rn = v.rn
       ) cv
       on c.id = cv.id
    set c.voucher = cv.voucher;