SQL迭代,同时迭代

时间:2014-07-24 09:52:57

标签: mysql vb.net

我是一名普通的VB程序员,但是对SQL很陌生并且正在努力解决我需要执行的一些事情。我正在寻找有关表格中特定记录更新的帮助,如下所示。

我在表中有一批当前未分配给客户的凭证(这些记录的字段已分配为零),我需要将这些凭证从特定批次的凭证中分配给特定的一组凭证中的10个客户。

客户在customers表中有唯一的ID,但我只想更新customer_type为'AABB'的客户

用于将一次性批量10分配给ID为4385的客户的SQL:

UPDATE vouchers
SET assigned_to_id = '4385'
WHERE batch_id = '9999999999'
AND assigned_to = '0'
LIMIT 10

我不知道该怎么做是创建一些例程或程序,选择适当的客户并依次用批次中的10张优惠券更新每个客户

这是我从customers表中选择customer_id的方法

SELECT customer_id from customers 
WHERE customer_type = ‘AABB’

我正在寻找的是实现这项工作的实际SQL。

我意识到下一步是不正确的,但这就是我看到我需要SQL工作的方式。我需要循环选择客户并将凭证(每次10个)更新到每个客户。

For each customer_id
    UPDATE vouchers
    SET assigned_to_id = customer_id
    WHERE batch_id = '9999999999'
    AND assigned_to = '0'
    LIMIT 10
Next customer_id

1 个答案:

答案 0 :(得分:1)

这可以在单个SQL语句中执行,但效率不高。

UPDATE vouchers
INNER JOIN 
(
    SELECT voucher_id, @cust_cnt1:=IF(@voucher_cnt < 10, @cust_cnt1, @cust_cnt1 + 1) AS cust_cnt, @voucher_cnt:=IF(@voucher_cnt < 10, @voucher_cnt + 1, 1)
    FROM vouchers
    CROSS JOIN(SELECT @voucher_cnt:=0, @cust_cnt1:=1) sub0
    WHERE batch_id = '9999999999'
    AND assigned_to_id = '0'
) sub1
ON vouchers.voucher_id = sub1.voucher_id
INNER JOIN
(
    SELECT customer_id, @cust_cnt2:=@cust_cnt2 + 1 AS cust_cnt
    FROM customers 
    CROSS JOIN(SELECT @cust_cnt2:=0) sub0
    WHERE customer_type = 'AABB'
) sub2
ON sub1.cust_cnt = sub2.cust_cnt
SET vouchers.assigned_to_id = sub2.customer_id;

这有一个针对凭证的子查询,它返回voucher_id(或凭证表所具有的任何唯一密钥,以及几个序列号。第一个序列号是后来为客户生成的匹配,而第二个序列号是从1开始的当第二个达到10时,第一个递增。这是你有10个代金券批次。

第二个子查询只返回带有计算序列号的客户ID。

然后基于来自第一个子查询的第一个序列号和来自第二个子查询的序列号来连接2个子查询。因此,对于任何匹配的客户ID,应该有2张优惠券。

然后将其加入凭证表(基于voucher_id)和用于填充assigned_to_id的customer_id。

一个SQL小提琴来证明这一点: -

http://www.sqlfiddle.com/#!2/58aa2a

编辑 - Mysql确实支持存储过程(尽管我对它们很有经验),它们允许你像在VB中那样进行处理(循环等)。

我已经快速敲定了以下存储过程,其中包含2个参数,一个是客户类型,另一个是批次ID,查找该客户的所有客户,然后更新所需批次ID的10个凭证以获得该客户ID。

您可以按如下方式创建存储过程(注意,您在数据库中创建一次,而不是每次都要创建它)

DELIMITER //
CREATE PROCEDURE UpdateVouchers(IN in_customer_type VARCHAR(255), IN in_batch_id VARCHAR(255))
BEGIN
    DECLARE not_found_customers INT DEFAULT 0;
    DECLARE fnd_customer_id INT;
    DECLARE csr_customers CURSOR FOR 
    SELECT customer_id from customers WHERE customer_type = in_customer_type;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET not_found_customers = 1;
    OPEN csr_customers;
    SET not_found_customers = 0;
    credit_loop : LOOP 
        FETCH csr_customers INTO fnd_customer_id;
        IF not_found_customers THEN
            CLOSE csr_customers;
            LEAVE credit_loop;
        END IF;
        UPDATE vouchers SET assigned_to_id = fnd_customer_id WHERE batch_id = in_batch_id AND assigned_to_id = '0' ORDER BY voucher_id LIMIT 10;
    END LOOP credit_loop;
END

然后您可以使用以下

执行它
CALL UpdateVouchers('AABB', '9999999999')
相关问题