TSQL: ОБНОВЛЕНИЕ с INSERT INTO ВЫБИРАЕТ ИЗ

Если человеку 1 не понравился человек 2, нет необходимости показывать человека 1 человеку 2. Даже если вы покажете его, они никогда не совпадут. Поэтому ваш расчет 1K x 1K = 1M немного завышен.

Однако, если вы все еще хотите иметь наборы лайков и дислайков для обоих пользователей, вы можете рассмотреть эту ужасную идею «сжатия» строк.

Представьте, что у вас есть последовательность, подобная этой:

| Person 1 | Person 2 |  Op       |
| -------- | -------- | --------- |
| 0001     | 1010     |  Dislike  |
| 0001     | 1011     |  Dislike  |
| 0001     | 1012     |  Dislike  |
| 0001     | 1013     |  Dislike  |
| 0001     | 1015     |  Like     |
| 0001     | 1017     |  Dislike  |
| 0001     | 1018     |  Dislike  |
| 0001     | 1019     |  Dislike  |
| 0001     | 1021     |  Like     |

Если у вас есть идентификаторы, следующие друг за другом, вы можете показать их как

| Person 1 | Person 2 |  Op       | N    |
| -------- | -------- | --------- | ---- |
| 0001     | 1010     |  Dislike  | 3    |
| 0001     | 1015     |  Like     | 0    |
| 0001     | 1017     |  Dislike  | 2    |
| 0001     | 1021     |  Like     | 0    |

где N - это максимальный идентификатор в последовательности ( например, 1010 + 3 = 1013). Если вы определите N как непоказанный tinyint, то максимально возможный размер последовательности может составить 255, то есть теоретически 255 последовательных дислайков / лайков можно сохранить как 1 запись.

И запрос будет примерно таким (представьте, что вы ищете идентификатор 1013):

SELECT a.* 
FROM (
    SELECT *
    FROM `table`
    WHERE person_1 = 0001
      AND person_2 >= (1013 - 255) -- 255 is a max size of a sequense 
      AND person_2 <= 1013
) a
WHERE a.person_2 <= 1013 AND a.person_2 + N >= 1013

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

| Person 1 | Person 2 |  Op       | N    |
| -------- | -------- | --------- | ---- |
| 0001     | 1010     |  Dislike  | 3    |

Но лично я бы пошел с этим и предпочел бы ваше текущее решение из-за его простоты.

ИЛИ как другой вариант, вы можете сжать таблицу таким образом

| Person 1 | Person 2 | Max Person 2 |  Op       |
| -------- | -------- | ------------ | --------- |
| 0001     | 1010     | 1013         |  Dislike  |
| 0001     | 1015     | 1015         |  Like     |
| 0001     | 1017     | 1019         |  Dislike  |
| 0001     | 1021     | 1021         |  Like     |
11
задан Undo 20 November 2013 в 17:52
поделиться

7 ответов

Ключ с миграцией состоит в том, чтобы сделать несколько вещей: Во-первых, не делайте ничего без текущей резервной копии. Во-вторых, если ключи будут меняться, вам нужно как минимум временно временно сохранить старое и новое в новой структуре (постоянно, если поле ключа открыто для пользователей, поскольку они могут искать его, чтобы получить старые записи).

Далее вам необходимо иметь полное представление об отношениях с дочерними таблицами. Если вы измените ключевое поле, все связанные таблицы также должны измениться. Здесь пригодится хранение старого и нового ключа. Если вы забудете изменить любой из них, данные больше не будут правильными и будут бесполезными. Так что это очень важный шаг.

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

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

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

Update t2
set fkfield = newkey
from table2 t2
join table1 t1 on t1.oldkey = t2.fkfield

Проверьте свою миграцию, выполнив контрольные примеры и сравнив данные с тем, что вы сохранили до миграции. Крайне важно тщательно протестировать данные миграции, иначе вы не можете быть уверены, что данные соответствуют старой структуре. Миграция - очень сложное действие; это платит, чтобы занять ваше время и делать это очень методично и тщательно.

Вы можете циклически проходить партии (не по одной записи за раз), чтобы повысить производительность. Если новый ключ является идентификатором, вы просто помещаете значение старого ключа в его поле и позволяете базе данных создавать новые ключи.

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

Update t2
set fkfield = newkey
from table2 t2
join table1 t1 on t1.oldkey = t2.fkfield

Проверьте свою миграцию, выполнив контрольные примеры и сравнив данные с тем, что вы хранили до миграции. Крайне важно тщательно протестировать данные миграции, иначе вы не можете быть уверены, что данные соответствуют старой структуре. Миграция - очень сложное действие; это платит, чтобы занять ваше время и делать это очень методично и тщательно.

Вы можете циклически проходить партии (не по одной записи за раз), чтобы повысить производительность. Если новый ключ является идентификатором, вы просто помещаете значение старого ключа в его поле и позволяете базе данных создавать новые ключи.

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

Update t2
set fkfield = newkey
from table2 t2
join table1 t1 on t1.oldkey = t2.fkfield

Проверьте свою миграцию, выполнив контрольные примеры и сравнив данные с тем, что вы сохранили до миграции. Крайне важно тщательно протестировать данные миграции, иначе вы не можете быть уверены, что данные соответствуют старой структуре. Миграция - очень сложное действие; это платит, чтобы занять ваше время и делать это очень методично и тщательно.

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

Update t2
set fkfield = newkey
from table2 t2
join table1 t1 on t1.oldkey = t2.fkfield

Проверьте свою миграцию, выполнив контрольные примеры и сравнив данные с тем, что вы хранили до миграции. Крайне важно тщательно протестировать данные миграции, иначе вы не можете быть уверены, что данные соответствуют старой структуре. Миграция - очень сложное действие; это платит, чтобы занять ваше время и делать это очень методично и тщательно.

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

Update t2
set fkfield = newkey
from table2 t2
join table1 t1 on t1.oldkey = t2.fkfield

Проверьте свою миграцию, выполнив контрольные примеры и сравнив данные с тем, что вы хранили до миграции. Крайне важно тщательно протестировать данные миграции, иначе вы не можете быть уверены, что данные соответствуют старой структуре. Миграция - очень сложное действие; это платит, чтобы занять ваше время и делать это очень методично и тщательно.

Убедитесь, что данные соответствуют старой структуре. Миграция - очень сложное действие; это платит, чтобы занять ваше время и делать это очень методично и тщательно.

Убедитесь, что данные соответствуют старой структуре. Миграция - очень сложное действие; это платит, чтобы занять ваше время и делать это очень методично и тщательно.

10
ответ дан 3 December 2019 в 04:33
поделиться

Лучшее, что я могу сделать, - это предложение вывода . Предполагая, что у вас SQL 2005 или 2008.

USE AdventureWorks;
GO
DECLARE @MyTableVar table( ScrapReasonID smallint,
                           Name varchar(50),
                           ModifiedDate datetime);
INSERT Production.ScrapReason
    OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate
        INTO @MyTableVar
VALUES (N'Operator error', GETDATE());

Для обновления исходной таблицы все равно потребуется второй проход; однако это может помочь упростить вашу логику. Вам нужно обновить исходную таблицу? Вы можете просто сохранить новые идентификаторы в третьей таблице перекрестных ссылок.

3
ответ дан 3 December 2019 в 04:33
поделиться

Вероятно, самым простым способом было бы добавить столбец в MV6.Posts для oldId, а затем вставить все записи из старый стол в новый стол. Наконец, обновите соответствие старой таблицы для oldId в новой таблице следующим образом:

UPDATE mv5.posts
SET newid = n.id
FROM mv5.posts o, mv6.posts n 
WHERE o.id = n.oldid

Вы можете очистить и удалить столбец oldId впоследствии, если хотите.

5
ответ дан 3 December 2019 в 04:33
поделиться

Хех. Я помню, как делал это во время миграции.

Помещение old_id в новую таблицу облегчает как обновление - вы можете просто вставить вставку в newtable select ... from oldtable , так и последующее «сшивание» записей. В «стежке» вы либо обновите внешние ключи дочерних таблиц во вставке, выполнив выборку нового родителя (вставка в newchild select ... (выберите id из new_parent, где old_id = oldchild.fk) как fk, ... из oldchild ) или вы вставите дочерние элементы и сделаете отдельное обновление для исправления внешних ключей.

Выполнение этого за одну вставку происходит быстрее; выполняя это на отдельном шаге, вы понимаете, что ваши вставки не зависят от порядка и могут быть повторно выполнены в случае необходимости.

После миграции,

2
ответ дан 3 December 2019 в 04:33
поделиться

Есть ли способ сделать это ОБНОВЛЕНИЕ через INSERT INTO SELECT FROM, чтобы мне не приходилось обрабатывать каждую запись вручную?

Так как вы не захотите сделать это вручную , но автоматически , создать триггер на MV6.Posts , чтобы ОБНОВЛЕНИЕ происходило на MV5.Posts автоматически, когда вы вставляете в MV6.Posts .

И ваш триггер может выглядеть примерно так:

create trigger trg_MV6Posts
on MV6.Posts
after insert
as
begin
    set identity_insert MV5.Posts on

    update  MV5.Posts
    set ID = I.ID
    from    inserted I

    set identity_insert MV5.Posts off
end
2
ответ дан 3 December 2019 в 04:33
поделиться

AFAIK, вы не можете обновить две разные таблицы с помощью одного оператора SQL

Однако вы можете использовать триггеры для достижения того, что Вы хотите сделать.

1
ответ дан 3 December 2019 в 04:33
поделиться

Создать столбец в MV6.Post.OldMV5Id

make вставить в MV6.Post выберите .. из MV5.Post

, затем обновите MV5.Post.MV6ID

1
ответ дан 3 December 2019 в 04:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: