2015-12-01 33 views
0

假設我有一個客戶端列表,並且我想將它們分配給一個總線。我有約翰,林戈,保羅.....他們可以在粉紅色或綠色巴士上旅行。這個想法是,配置將是以連續順序更新包含記錄的表格

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'); 
+0

使用'ROW_NUMBER()over'指定序號。通過case語句或映射表將序號映射到公共汽車,然後根據序號更新 –

回答

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; 
+0

哇哇。這是驚人的HABO。我非常感謝你對我的問題的幫助。只是你花費在其上的時間。非常感謝你 –

0

我假設您希望將客戶端交替分配給粉紅色,然後是綠色公交車 - 這是不清楚你的問題。

您可以將自動遞增列添加到客戶端表中,然後使用更新語句將模塊除以2?

客戶表將是這樣的:

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語句會那麼同樣是UPDATE BusAllocation SET BusAllocation = 'Pink' WHERE ClientName IN (SELECT ClientName FROM Client WHERE ClientId % 2 = 1)

如果您想要非常嚴格,您可能想要避免選擇這個列作爲PK - 只需添加一個輔助列即可。

+0

感謝所有您的迴應。讓我再澄清一點。我給出的表格不是我的問題表格。我剛把問題簡化到儘可能簡單。不能硬編碼粉紅色或綠色。爲什麼還有另一個帶有值的表格,所以我們可以添加一些像紫色的東西作爲公共汽車。至於主鍵這是一個測試案例..任何人都有任何思想彎曲的想法? –

1

這裏讓我們大多數人感到困惑,爲什麼你不使用Id列。但是,如果它像你所說的那麼簡單,那麼這將是實現你想要的最小代碼。

DECLARE @RowIndex int = 0 

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

我懷疑當你進入下一步時,你會意識到標識列的值,並在每個表上放一個。然後會有一個客戶表,總線表和總線分配表。 BusAllocation表將具有ClientId和BusId列,這就是將總線分配給客戶端的方式。

+0

這是一個非常優雅的解決方案 - 我從來沒有見過在集合操作中迭代變量的技術。 –

+0

僅供參考 - 此技術在此處的MSDN文檔中進行了說明:https://technet.microsoft.com/zh-cn/library/ms177523(v=sql.105).aspx#ColumnValues 謝謝@JBrooks。 –