2015-06-24 3 views
3

У меня есть набор данных, который я получил от XML и его вспыхнувший со следующей структурой:Необходимость обновления T-SQL заявление динамически назначить номер записи

[Таблица данных]

[ID] [Name]  [Value] 
1 ad1_pk  1 
2 ad1_addr1 123 Easy Street 
3 ad1_pk  2 
4 ad1_addr1 99 US31 
5 ad1_atfk 6 
6 ad1_pk  3 
... {and so on} 

Я добавил столбец (называемый recNum), чтобы указать отдельный номер записи; однако я не нашел быстрый способ установить номер записи для каждой записи. Количество строк, указывающих отдельную запись, может меняться, поэтому я хочу, чтобы оператор обновления мог справиться с этим. Каждая «запись» имеет имя столбца, которое заканчивается на «_pk», поэтому я определяю начало каждой записи в наборе данных.

Я успешно справился с циклом while, но это слишком медленно, и таблицы могут иметь миллионы записей. Пример:

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

insert into myNewTable ({column name list}) VALUES ({value list}) 

... [обновлено 2015-06-24 00:26 EDT] Это как далеко я получили до сих пор ... https://drive.google.com/file/d/0B82UP-AIFz_ITlNIb1ZwSFdyODg/view?usp=sharing

SELECT TOP 100 
z2.ID,z2.Name,z2.Value,CASE WHEN z2.ID=RecIDs.ID THEN z2.Value ELSE NULL END RecNum 
FROM MyTable 2 
LEFT JOIN (
    SELECT DENSE_RANK() OVER (ORDER BY ID) drn,ID FROM MyTable 
    WHERE RIGHT(name,3)='_pk' 
) RecIDs ON RecIDs.ID = z2.ID 
ORDER BY ID 

... Мне нужно, чтобы заполнить пробелы. Любые предложения?

[обновлено 2015-06-25 9:33 EDT] Это для SQL Server 2008 R2

+0

Если вам действительно нужна помощь, пожалуйста, облегчите людям помощь. Для справки о том, как это сделать: [Советы по заданию хорошего вопроса о структурированном запросе языка (SQL)] (http://meta.stackoverflow.com/questions/271055/tips-for-asking-a-good-structured-query -language-sql-question) – har07

+0

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

+0

, какую версию сервера sql вы используете? – ughai

ответ

2

Во-первых, вы хотите, чтобы присвоить значение для RecNum для всех PK с использованием ROW_NUMBER. После этого, вы хотите обновить оставшиеся строки с подходящей RecNum

SQL Fiddle

WITH CtePKs AS(
    SELECT *, 
     RN = ROW_NUMBER() OVER(ORDER BY ID) 
    FROM z2 
    WHERE RIGHT(Name, 3) = '_pk' 
) 
UPDATE CtePKs SET RecNum = RN 

UPDATE z 
    SET RecNum = x.RecNum 
FROM z2 z 
OUTER APPLY(
    SELECT TOP 1 Id, RecNum 
    FROM z2 
    WHERE 
     ID < z.ID 
     AND RecNum IS NOT NULL 
    ORDER BY ID DESC 
)x 
WHERE z.RecNum IS NULL 

РЕЗУЛЬТАТ

| ID |  Name |   Value | RecNum | 
|----|-----------|-----------------|--------| 
| 1 | ad1_pk |    1 |  1 | 
| 2 | ad1_addr1 | 123 Easy Street |  1 | 
| 3 | ad1_pk |    2 |  2 | 
| 4 | ad1_addr1 |   99 US31 |  2 | 
| 5 | ad1_atfk |    6 |  2 | 
| 6 | ad1_pk |    3 |  3 | 
+0

Как мне получить значение от CTE до окончательного оператора обновления, поскольку CTE доступны только один раз? – wk4997

+0

Что это значит? Первое 'UPDATE' в' CTE' также обновляет свою справочную таблицу. –

+0

Итак, я получил первое заявление об обновлении CTE. Тем не менее, теперь есть проблема, которую я обнаружил со второй, когда она слишком долго подходит для обновления. – wk4997

1

Вы можете использовать cte для этого:

;With cte as (
    SELECT [id], Row_number() OVER(Order by [id] As rn 
    FROM MyTable 
) 

UPDATE MyTable 
SET recNum = rn 
FROM MyTable t 
INNER JOIN cte ON(t.[id] = cte.[id]) 

Однако, вам так уже есть идентификатор столбца, который, кажется, есть значения, которые вы просите, вы можете просто сделать это:

UPDATE MyTable 
SET recNum = [id] 
+1

Это не делает то, что я хочу, так как мне нужно добавить столбец, чтобы указать «запись», которая существует. Просмотрите мои обновления. – wk4997

2

Если я правильно понимаю ваш вопрос, вы можете использовать коррелированный подзапрос, как это. Если вы используете SQL Server 2012 или выше, вы также можете использовать SUM() OVER(). Проверьте Изменить.

Примеры данных

CREATE TABLE Table1 
    ([ID] int,rowid int, [Name] varchar(9), [Value] varchar(15)); 

INSERT INTO Table1 
    ([ID], [Name], [Value]) 
VALUES 
    (1, 'ad1_pk', '1'), 
    (2, 'ad1_addr1', '123 Easy Street'), 
    (3, 'ad1_pk', '2'), 
    (4, 'ad1_addr1', '99 US31'), 
    (5, 'ad1_atfk', '6'), 
    (6, 'ad1_pk', '3'); 

Запрос

UPDATE Table1 
SET rowid = 
(SELECT COUNT(ID) FROM Table1 T2 WHERE T2.ID <= Table1.ID AND T2.Name Like '%[_]pk'); 

SELECT * FROM Table1; 

SQL Fiddle

ВЫВОД

| ID | rowid |  Name |   Value | 
|----|-------|-----------|-----------------| 
| 1 |  1 | ad1_pk |    1 | 
| 2 |  1 | ad1_addr1 | 123 Easy Street | 
| 3 |  2 | ad1_pk |    2 | 
| 4 |  2 | ad1_addr1 |   99 US31 | 
| 5 |  2 | ad1_atfk |    6 | 
| 6 |  3 | ad1_pk |    3 | 

EDIT

Для SQL Server 2012 или выше

Запрос

;WITH CTE AS 
(
SELECT SUM(CASE WHEN Name LIKE '%[_]pk' THEN 1 ELSE 0 END) OVER(ORDER BY ID) recnum,* 
FROM Table1 
) 
    UPDATE CTE 
    SET rowid = recnum; 

    SELECT * FROM Table1; 

SQL Fiddle

+1

отформатировал ваш результат на основе результата скрипта sql. –

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