2017-09-26 85 views
0

我有一组查询用于根据其序列号更新来自另一个表(cards)的代码的表(boxes)。序号为1的卡进入boxes表中名为code_1的列,以此类推,以获得有限数量的可能序列号。因为它是有限的,我可以这样做:SQL - 将值更新到编号列中

update b 
    set code_1 = c.codes 
    from boxes as b inner join cards as c 
     on b.service_id = c.service_id and c.sequence_number = 1; 
update b 
    set code_2 = c.codes 
    from boxes as b inner join cards as c 
     on b.service_id = c.service_id and c.sequence_number = 2; 
update b 
    set code_3 = c.codes 
    from boxes as b inner join cards as c 
     on b.service_id = c.service_id and c.sequence_number = 3; 
... 
update b 
    set code_n = c.codes 
    from boxes as b inner join cards as c 
     on b.service_id = c.service_id and c.sequence_number = n; 

但我的问题是:是否有编写一个查询,将适当的基于源的序列号更新所有列的方式吗?

+1

'n'是已知的固定值,还是可以变化? –

+0

@PhilipKelley'n'因给定的'service_id'而有所不同,但确实有一个最大值,所以如果需要的话我可以硬编码。 – Michael

+0

另外,你使用的是什么RDBMS? –

回答

0

你可以用下面的代码

UPDATE b 
    SET code_1 = CASE sequence_number 
     WHEN 1 THEN 3 
     WHEN 2 THEN 4 
     WHEN 3 THEN 5 
    END, 
    code_2 = CASE sequence_number 
     WHEN 1 THEN 'New Title 1' 
     WHEN 2 THEN 'New Title 2' 
     WHEN 3 THEN 'New Title 3' 
    END 
WHERE sequence_number IN (1,2) 

做到这一点,据我所知,就可以实现从这种多多次更新。希望这可以帮助你。

0
update b set code_1 = (select c.codes from cards as c on b.service_id = i.service_id and c.sequence_number = 1), 
code_2= (select c.codes from cards as c on b.service_id = i.service_id and c.sequence_number = 2), 
code_3= (select c.codes from cards as c on b.service_id = i.service_id and c.sequence_number = 3), 
. 
. 
. 
code_n= (select c.codes from cards as c on b.service_id = i.service_id and c.sequence_number = n); 
0

嗯......如果你不想硬编码它,也许你可以使用循环代替方法。我不是超强的SP的,但这样的事情:

DECLARE @LoopCounter INT = 1, @codeNumber int; 

WHILE (SELECT boxID FROM boxes)< (select max(boxID) as boxIDMax from boxes) 
BEGIN 
SET @codeNumber= <get_your_codeID_here_with_select_where_boxID=codeID> 

update b 
    set @codeNumber = c.codes 
    from boxes as b inner join cards as c 
     on b.service_id = i.service_id and c.sequence_number = boxID; 

SET @LoopCounter = @LoopCounter + 1; 

END 
+0

这不起作用,因为您不能使用变量('@ codeNumber')来指定正在更新的列。使用循环来创建并执行动态SQL语句 - 但这仍然是几个查询。 –

0

您可以通过使用PIVOT

;WITH T AS (
select * from 
    (select * from cards) src 
     pivot (MAX(codes) for sequence_number IN ([1],[2],[3],...,[n])) pvt 
) 
update b 
SET 
    code_1 = T.[1], 
    code_2 = T.[2], 
    code_3 = T.[3], 
    ...., 
    code_n = T.[n] 
from 
    boxes b 
    inner join T ON b.service_id = T.service_id 
0

将要更新的列的数量在设计时是不知道的事实使它意味着严格来说,这不能在单个查询中完成。您需要构建然后执行动态SQL查询来执行此操作。

@Troels答案是一种方法来处理N上的这个循环,并为每个迭代问题和更新。这会比现在更方便的代码,可能是你真正想要的,但不是一个单一的查询。通过建立从一箱的连接到卡

  • 使用此

    • 动态生成查询,用N“项”
    • 开始:

      为了让你不得不单查询作为pivot语句中的子查询,为每个Item生成一个列(这是动态SQL是强制性的)

    • 使主要查询成为CTE的第一部分
    • 接下来,将框连接到CTE tableset上service_id为
    • 使它成为一个更新语句,用N(动态生成的)设置子句中的项目,设置为从枢轴集中适当的列中的值(和一定要检查并妥善处理空值)

    这将是一个痛苦的写作和轻微的头痛随着时间的推移进行修改。除非有很强的理由(需要成为一个单独的事务),否则我会从@Troels版本开始,并添加动态SQL。

    如果当然,不得不说的是,最好的办法是规范表boxes,以便它不包含未知的行数,说,Boxes(主键box_id)和BoxContents(主键box_id, sequence_number

    ...当我写这篇文章时,@ sarslan的主要答案就出现了,正是我所说的。如果你知道N,它就可以工作,但如果你不知道,必须建立并运行。