Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
Veligord Member Откуда: Москва Сообщений: 92 |
Есть вот такая таблица:CREATE TABLE [dbo].[T_Blank]( [ID] [bigint] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL, [UserID] [int] NULL, [Created] [datetime] NULL, [CancelDate] [datetime] NULL CONSTRAINT [PK_T_Blank] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY] ) ON [PRIMARY] В ней около 3 миллионов записей. В нее добавили столбец [SetId] [bigint] NULL. Необходимо заполнить этот столбец (SetId) числами от 1 до n, где n - количество пользователей. Если есть записи с одинаковым, то для этих записей SetId - одинаковый. Написал такой запрос: declare @id int declare @userId int declare @uId int = 0 declare @setId int = 0 declare curWorkTable cursor LOCAL fast_forward read_only for SELECT ID, UserId from T_Blank open curWorkTable FETCH NEXT FROM curWorkTable INTO @id, @userId WHILE @@FETCH_STATUS = 0 BEGIN if @uId != @userId set @setId = @setId + 1 update T_Blank set SetID = @setId where ID = @ID set @uId = @userId FETCH NEXT FROM curWorkTable INTO @id, @userId END close curWorkTable Но он на 3 миллионах записей он будет работать ну ооочень долго. Можно ли его переписать без курсора? |
20 авг 13, 17:51 [14732272] Ответить | Цитировать Сообщить модератору |
Shakill Member Откуда: мск Сообщений: 1882 |
Veligord, а в каком порядке должны обрабатываться данные? в курсоре почему-то не видно ORDER BY |
20 авг 13, 18:07 [14732364] Ответить | Цитировать Сообщить модератору |
Winnipuh Member [заблокирован] Откуда: Київ Сообщений: 10428 |
немного сумбурно выглядит... или я не понял... что вы здесь подсчитываете? if @uId != @userId set @setId = @setId + 1 |
20 авг 13, 18:09 [14732374] Ответить | Цитировать Сообщить модератору |
aleks2
Guest |
Ну... изучите DENSE_RANK() что ли? |
||
20 авг 13, 18:19 [14732419] Ответить | Цитировать Сообщить модератору |
aleks2
Guest |
НО я бы сделал тупо и прямолинейноdeclare @t table(UserID [int] primary key clustered, i int identity); insert @t (UserID) select distinct UserID from [dbo].[T_Blank]; update b set SetId = t.i from [dbo].[T_Blank] b inner join @t t on b.UserID = t.UserID; |
20 авг 13, 18:26 [14732444] Ответить | Цитировать Сообщить модератору |
Veligord Member Откуда: Москва Сообщений: 92 |
Shakil, Order by ID asc Winnipuh, if @uId != @userId set @setId = @setId + 1 это проверка - если id пользователя изменилось, то SetId нужно увеличить на 1 |
21 авг 13, 10:17 [14734345] Ответить | Цитировать Сообщить модератору |
Ivan Durak Member Откуда: Minsk!!! Сообщений: 3646 |
UPDATE T SET SetId = sub.cnt FROM dbo.T_Blank T inner join ( select ID, count(UserID) as cnt FROM dbo.T_Blank group by ID ) sub on sub.ID = T.ID |
21 авг 13, 10:36 [14734459] Ответить | Цитировать Сообщить модератору |
Veligord Member Откуда: Москва Сообщений: 92 |
Ivan Durak, Спасибо, но это немного не то, что мне нужно. Этот скрипт заполняет SetId количеством вхождений пользователя в таблице. А мне нужно, чтобы было просто перечисление от 1 до n. Но, чтобы для одного пользователя SetId был одинаковый. Да, к тому же у меня этот скрипт почему-то заполняет SetId только единиицами. Хотя многие пользователи повторяются десятки и сотни раз.UPDATE T SET SetId = sub.cnt FROM dbo.T_Blank T inner join ( select ID, count(UserID) as cnt FROM dbo.T_Blank group by ID ) sub on sub.ID = T.ID |
21 авг 13, 14:06 [14736106] Ответить | Цитировать Сообщить модератору |
Shakill Member Откуда: мск Сообщений: 1882 |
Veligord, а если записи с одинаковым UserId идут не подряд (order by id), то у них должен быть одинаковый setId или разный? |
21 авг 13, 14:18 [14736186] Ответить | Цитировать Сообщить модератору |
Veligord Member Откуда: Москва Сообщений: 92 |
Одинаковый |
21 авг 13, 14:47 [14736465] Ответить | Цитировать Сообщить модератору |
Veligord Member Откуда: Москва Сообщений: 92 |
Всем спасибо, сделал вот так:UPDATE T SET SetId = sub.setId FROM dbo.T_Blank as T inner join ( select ID, Dense_RANK() OVER(ORDER BY CashierId) as setId from dbo.T_Blank ) sub on sub.ID = T.ID |
21 авг 13, 15:03 [14736614] Ответить | Цитировать Сообщить модератору |
iap Member Откуда: Москва Сообщений: 47049 |
WITH CTE AS(SELECT SetId,NewSetId=DENSE_RANK()OVER(ORDER BY CashierId) FROM dbo.T_Blank) UPDATE CTE SET SetId=NewSetId; |
||
21 авг 13, 15:27 [14736860] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |