2015-12-01 7 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() над' для присвоения порядкового номера. Сопоставьте порядковый номер с шиной через оператор 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

Wow wow wow. Это потрясающе 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 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 

Я подозреваю, что когда вы перейдете к следующему шагу, вы поймете значение столбцов идентификации и поместите их на каждую из таблиц. Тогда будет таблица Client, таблица Bus и таблица BusAllocation. Таблица BusAllocation будет иметь столбец ClientId и BusId, и именно так вы назначаете шину клиенту.

+0

Это очень элегантное решение - я никогда не видел эту технику итерации переменной в заданной операции. –

+0

Для справки - эта методика указана в документации MSDN здесь: https://technet.microsoft.com/en-us/library/ms177523(v=sql.105).aspx#ColumnValues ​​ Спасибо @JBrooks. –

Смежные вопросы