我有一个表( customerselection ),其中列出了客户编号和促销代码:
CustomerNumber | Promo
12345 | ABCDEF
54321 | BCDEFG
22334 | BCDEFG
54678 | BCDEFG
23454 | ABCDEF
另一个表(证书)列出了Certificates,Promos和CustomerNumbers,但CustomerNumber最初为NULL:
Certificate | Promo | CustomerNumber
1111111111 | ABCDEF | NULL
2222222222 | BCDEFG | NULL
3333333333 | BCDEFG | NULL
4444444444 | ABCDEF | NULL
我需要做的是将第二个表中的每个证书唯一地分配给第一个表中的客户。促销需要匹配。使用匹配的促销更新第二个表,其中包含从第一个,仅一个记录的客户编号。
我以前用VB程序完成了这个 - 在第一个表中循环记录,更新第二个表中匹配促销的第一个免费记录。但是该程序运行时间太长(通常有大约600,000条记录)。
有没有办法在SQL中正确执行此操作?用一个非常复杂(甚至非常简单)的SQL查询来完成任务? (或SQL Server功能?)
UPDATE 每个促销都有许多证书。每个促销活动都有很多客户。
但每位客户只能分配一份证书。
更新2 我们先调用第一个表 customerselection ,然后调用第二个表证书。
customerselection 是我们要为其分配证书的一系列客户。
证书是可以分配的证书池。
答案 0 :(得分:1)
试试这个
UPDATE
B
SET
B.CustomerNumber = A.CustomerNumber
FROM
TableB B
INNER JOIN
TableA A
ON
B.Promo = A.Promo
答案 1 :(得分:1)
如果我理解正确,您希望匹配证书和客户,以便每个客户和每个证书出现一次(对于每个促销)。 即对于给定的促销
custD, custR, custA
cert2 *
cert1 *
cert3 *
cert6
cert7
重要的是每行和每列最多只有一个匹配。
update certificates
set CustomerNumber = t_cust.CustomerNumber
from certificates,
( select Promo, CustomerNumber,
row_number() over (partition by Promo order by CustomerNumber) as order_cust
from customerselection
) t_cust,
( select Promo, Certificate,
row_number() over (partition by Promo order by Certificate) as order_cert
from certificates
) t_cert
where t_cust.Promo = t_cert.Promo
and t_cust.order_cust = t_cert.order_cert
and certificates.Certificate = t_cert.Certificate
答案 2 :(得分:0)
将表格称为A和B,并且根据您的问题,我知道表B中的每个促销可能有多个证书。因此,我选择了B中较低证书编号的第一个记录,并将其与A匹配。并更新了B的相应的客户编号。
以下是我发布的http://www.sqlfiddle.com/#!6/726a6/30
解决方案的sqlfiddle UPDATE B
SET B.CustomerNumber = A.CustomerNumber
FROM A,
(SELECT * FROM (
SELECT b.*, ROW_NUMBER ( ) OVER ( partition BY Promo ORDER BY certificate ) AS row_num
FROM B b
) t WHERE row_num = 1) AS r
WHERE A.Promo=r.promo
and b.CustomerNumber is null;
答案 3 :(得分:0)
由于问题已更新,我也必须更新我的答案
Declare @c table (CustomerNumber int, Promo Varchar(50))
Insert into @c
SELECT 12345 ,'ABCDEF'
UNION SELECT 54321,'BCDEFG'
UNION SELECT 54321,'XXXXXX'
UNION SELECT 77777,'XXXXXX'
Declare @ce table (Certificate bigint,Promo Varchar(50), CustomerNumber int)
insert into @ce
SELECT 1111111111,'ABCDEF',NULL
UNION SELECT 2222222222,'BCDEFG',NULL
UNION SELECT 3333333333,'XXXXXX',NULL
UNION SELECT 4444444444,'ABCEDF',NULL
Update ce set CustomerNumber = z.CustomerNumber
from
(
Select CustomerNumber,Certificate from
(select *,ROW_NUMBER() over (order by CustomerNumber) as rn
from
(
Select DISTINCT CustomerNumber from @c
) x)x
JOIN
(Select *,ROW_NUMBER() over (order by Certificate) as rn from
(
Select DISTINCT Certificate
from @ce) y
) y on x.rn=y.rn
) z join @ce ce on ce.Certificate=z.Certificate
Select * from @ce
答案 4 :(得分:0)
您需要为每个促销分配一个客户和确保客户不会因同一促销而被使用两次。
关键是通过促销枚举两个表。然后按编号进行匹配:
with toupdate as (
select c.*, row_number() over (partition by Promo order by newid()) as seqnum
from Certificates c
),
customers as (
select cs.*, row_number() over (partition by Promo order by newid()) as seqnum
from customerselection cs
)
update toupdate
set CustomerNumber = customers.CustomerNumber
from toupdate join
customers
on toupdate.promo = customers.promo and
toupdate.seqnum = customers.seqnum;
这将确保一个客户不会被分配两次到同一个促销,除非客户在customerselection
表中有两行。