按顺序更新包含记录的表

时间:2015-12-01 01:39:26

标签: sql sql-server tsql

假设我有一个客户列表,我想将它们分配给总线。我有John,Ringo,Paul .....他们可以乘坐粉红色或绿色巴士。我们的想法是分配

John: Pink
Ringo: Green
Paul: Pink

有没有人知道如何在不诉诸循环声明的情况下做到这一点?

--DROP TABLE [BusAllocation]
CREATE TABLE [dbo].[BusAllocation]
(
    [ClientName] [varchar](50) NOT NULL,
    [BusAllocation] [varchar](50) NULL
);

INSERT INTO BusAllocation([ClientName]) VALUES('John');
INSERT INTO BusAllocation([ClientName]) VALUES('Ringo');
INSERT INTO BusAllocation([ClientName]) VALUES('Paul');
INSERT INTO BusAllocation([ClientName]) VALUES('Simon');
INSERT INTO BusAllocation([ClientName]) VALUES('Tyrone');

CREATE TABLE [dbo].[Bus]
(
    BusName [varchar](50) NOT NULL,
);

INSERT INTO [Bus](BusName) VALUES('Pink');
INSERT INTO BusAllocation([ClientName]) VALUES('Green');

3 个答案:

答案 0 :(得分:1)

我们大多数人为什么不使用Id列令人困惑。但是,如果它就像你说的那么简单,这将是实现你想要的最小代码。

DECLARE @RowIndex int = 0

UPDATE BusAllocation
SET BusAllocation = CASE WHEN @RowIndex % 2 = 0 THEN 'Pink' ELSE 'Green' END, 
@RowIndex = @RowIndex + 1

我怀疑当你进入下一步时,你将意识到身份列的价值,并在每个表上放置一个。然后会有一个Client表,Bus表和BusAllocation表。 BusAllocation表将具有ClientId和BusId列,这就是您将总线分配给客户端的方式。

答案 1 :(得分:0)

我假设您希望将客户交替分配给粉红色然后是绿色公共汽车 - 这不是您的问题所在。

您可以将自动递增列添加到Client表,然后使用带有更新语句的模块除2吗?

Client表格如下:

CREATE TABLE Client (
    ClientId INT IDENTITY(1,1) NOT NULL,
    ClientName varchar(50) NOT NULL
)

第一个更新语句如下所示:

UPDATE BusAllocation
SET BusAllocation = 'Green'
WHERE ClientName IN (SELECT ClientName FROM Client WHERE ClientID % 2 = 0)

第二个更新声明同样是UPDATE BusAllocation SET BusAllocation = 'Pink' WHERE ClientName IN (SELECT ClientName FROM Client WHERE ClientId % 2 = 1)

如果您想要非常严格,您可能希望避免将此选择列作为PK - 只需添加一个辅助列。

答案 2 :(得分:0)

以下代码演示了基本技术。希望真正的表格有一些独特的字段,可用于提供代替( order by ( select NULL ) )黑客的订单。

请注意,代码会为每行生成数字,而与其他任何数据无关。它不会因身份价值的差距而绊倒,例如:删除行或回滚事务时。

-- Sample data.
declare @BusAllocation as Table ( ClientName VarChar(10), BusAllocation VarChar(10) );
insert into @BusAllocation values
  ( 'John', NULL ), ( 'Ringo', NULL ), ( 'Paul', NULL ), ( 'Simon', NULL ), ( 'Tyrone', NULL );
select * from @BusAllocation;

declare @Bus as Table ( BusName VarChar(10) );
insert into @Bus values
  ( 'Pink' ), ( 'Green' );
select * from @Bus;

-- Mix and match the buses and output the result.
with
  NumberedBuses as (
    select BusName, Row_Number() over ( order by ( select NULL ) ) - 1 as RN
      from @Bus ),
  NumberedClients as (
    select ClientName, Row_Number() over ( order by ( select NULL ) ) - 1 as RN
      from @BusAllocation )
  select NC.RN, ClientName, BusName
    from NumberedClients as NC inner join
      NumberedBuses as NB on NB.RN = NC.RN % ( select count(42) from NumberedBuses )
    order by NC.RN;

-- Do it again updating the table.
with
  NumberedBuses as (
    select BusName, Row_Number() over ( order by ( select NULL ) ) - 1 as RN
      from @Bus ),
  NumberedClients as (
    select ClientName, Row_Number() over ( order by ( select NULL ) ) - 1 as RN
      from @BusAllocation )
  update @BusAllocation
    set BusAllocation = NB.BusName
    from @BusAllocation as BA inner join
      NumberedClients as NC on NC.ClientName = BA.ClientName inner join
      NumberedBuses as NB on NB.RN = NC.RN % ( select count(42) from NumberedBuses );

 select * from @BusAllocation;