Обновить номер на основе его уникального идентификатора - PullRequest
0 голосов
/ 01 октября 2009

У меня есть таблица в SQL Server, где у меня есть уникальный SiteNumber для каждого уникального location_id. То, что я пытаюсь сделать, это увеличить каждый номер ситема на 1, если location_id отличается.

Например:

SITENUM              LOCATION_ID
1234                 8801
4567                 8802
8910                 8803

... и т. Д.

Допустим, теперь я вставил новые значения для LOCATION_ID, но мой SITENUM остается NULL

NULL                 7000
NULL                 7001
NULL                 7002
1234                 8801
4567                 8802

и т.д.

Моя логика гласит, что ситенум для 7000 должен быть MAX(select * sitenum from table) но следующая ситена для 7001 должна быть Max(select * sitenum from table)+1

Прямо сейчас следующий код обновляет все ситены сразу до ТОЧНОГО одинакового значения

UPDATE dbo.[Monthly Hierarchy Table]
SET SITENUM = MAX(SELECT SITENUM FROM [Monthly Hierarchy Table])+1
WHERE SITENUM IS NULL and location_id is not null

Но я действительно хочу, чтобы это происходило, переходя строка за строкой, просматривая max(sitenum) и увеличивая его на основе недублированных идентификаторов location_id. Должен быть какой-то способ, которым я могу сравнивать каждый location_id с самим собой и увеличивать номер места, где бы он ни был нулевым, а location_id отличается

Как мне это сделать? Может быть, то, как я понимаю, это не правильно, но это довольно простая проблема.

Ответы [ 4 ]

1 голос
/ 01 октября 2009

Прежде всего, вы получили функцию MAX() не в том месте, поэтому она должна выглядеть следующим образом:

UPDATE dbo.[Monthly Hierarchy Table]
SET SITENUM = (SELECT MAX(SITENUM)+1 FROM [Monthly Hierarchy Table])
WHERE SITENUM IS NULL and location_id is not null

К сожалению, это все равно не поможет, потому что базы данных sql обычно вычисляют новые значения для всех строк перед обновлением любых строк. Это означает, что вы будете обновлять их все до одного значения.

Итак, вместо этого вам нужно сделать это с помощью нескольких утверждений:

BEGIN TRANSACTION
    DECLARE @NewSiteNum int
    SELECT @NewSiteNum = MAX(SiteNum)+1 FROM [Monthly Hierarchy Table]

    UPDATE dbo.[Monthly Hierarchy Table]
    SET SITENUM = SELECT @NewSiteNum,
        @NewSiteNum = @NewSiteNum + 1
    WHERE SITENUM IS NULL and location_id is not null
COMMIT

Обратите внимание на транзакцию здесь: это очень важно, иначе ваши SiteNums могут не оказаться уникальными.

0 голосов
/ 01 октября 2009

Вот один запрос (без процедурного кода, рекурсии или курсоров), который выполняет эту работу:

(из вашего вопроса я не уверен, может ли таблица иметь дублирующиеся идентификаторы местоположения, поэтому в моем решении строки с одинаковыми идентификаторами местоположения получают дублирующиеся места)

drop table t
go
create table t (sitenum int, locid int)
go
insert into t(sitenum, locid) values (null, 7000)
insert into t(sitenum, locid) values (null, 7000)
insert into t(sitenum, locid) values (null, 7001)
insert into t(sitenum, locid) values (null, 7002)
insert into t(sitenum, locid) values (1234, 8801)
insert into t(sitenum, locid) values (4567, 8802)
go 

update t4 set sitenum = t3.new_sitenum from
t t4 inner join
(
    select t1.locid, COUNT(*) + (select MAX(sitenum) from t) as new_sitenum from
        (select locid from t where sitenum is null group by locid) as t1
        inner join
        (select locid from t where sitenum is null group by locid) as t2
        on t1.locid >= t2.locid
    group by t1.locid
) as t3
on t4.locid = t3.locid

select * from t

Результаты:

sitenum locId
4568    7000
4568    7000
4569    7001
4570    7002
1234    8801
4567    8802

Ключом к этому является самостоятельное присоединение стола к себе. Условие соединения:

t1.locId> = t2.locId

Затем вы группируете по t1.locId и используете агрегат COUNT (*), чтобы получить число, которое эффективно считается от 1 для каждой строки. Самые внутренние GROUP BY предназначены для работы с дублирующимися идентификаторами. Наконец, обновите, присоединив locId к подзапросу.

0 голосов
/ 01 октября 2009

Вы можете сделать что-то вроде этого:

declare @num int;
set @num = (select max(LOCATION_ID) from MyTable);
update MyTable 
set SITENUM = @num, @num = @num + 1
where SITENUM is null and LOCATION_ID is not null
0 голосов
/ 01 октября 2009

Проблема в том, что агрегатная функция max () вычисляет максимальное значение один раз, а затем применяет это значение ко всем записям, соответствующим предложению where. Это природа транзакционной / ACID-совместимой базы данных - отдельные обновления каждой записи не видны вам до тех пор, пока вся транзакция не завершится успешно.

Возможно, вам понадобится написать небольшую хранимую процедуру, в которой используется курсор, проходящий по каждой нулевой записи ситена; не должно быть так сложно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...