Как дублировать записи, изменять и добавлять их в одну таблицу

#sql #sql-server #temp-tables

#sql #sql-сервер #временные таблицы

Вопрос:

У меня есть вопрос, и, надеюсь, вы сможете мне помочь. 🙂

У меня есть такая таблица:

 ID  Col1        Col2        ReverseID
1   Number 1    Number A    
2   Number 2    Number B    
3   Number 3    Number C    
  

Чего я хочу добиться, так это:

  • Создайте дубликат каждой записи с переключаемыми столбцами и добавьте их в исходную таблицу
  • Добавьте идентификатор дубликата в столбец ReverseID исходной записи и наоборот

Итак, новая таблица должна выглядеть так:

 ID  Col1        Col2        ReverseID
1   Number 1    Number A    4
2   Number 2    Number B    5
3   Number 3    Number C    6
4   Number A    Number 1    1
5   Number B    Number 2    2
6   Number C    Number 3    3

  

То, что я делал до сих пор, работало с временной таблицей:

 SELECT * INTO #tbl
FROM myTable

UPDATE #tbl
SET Col1 = Col2,
    Col2 = Col1,
    ReverseID = ID

INSERT INTO DUPLICATEtable(
        Col1,
        Col2,
        ReverseID
)

SELECT Col1,
       Col2,
       ReverseID
FROM #tbl
  

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

Я думаю, что мог бы пропустить часть SET и изменить столбцы в последнем операторе SELECT, чтобы добиться того же, но я не уверен.

В любом случае — с этим я заканчиваю:

 ID  Col1        Col2        ReverseID
1   Number 1    Number A    
2   Number 2    Number B    
3   Number 3    Number C    
4   Number A    Number 1    1
5   Number B    Number 2    2
6   Number C    Number 3    3

  

Итак, остается вопрос: как мне правильно добавить обратные идентификаторы в исходные записи?

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

Заранее благодарю!

br mrt

Редактировать:

Я пытаюсь проиллюстрировать свою первоначальную проблему, поэтому эта публикация становится длинной. 😉

РЕД
.

Прежде всего: мой интерфейс не допускает никаких инструкций SQL, я должен сосредоточиться на классах, атрибутах, отношениях.

Первая основная причина: экземпляры класса B (B1, B2, B3, …) связаны друг с другом отношением класса, это отношения «многие ко многим» одного класса. Мой интерфейс не позволяет объединять таблицы, так что это обходной путь.

Указание пользователя добавляет связь с B1 в качестве первой стороны (я просто назвал ее «левой») и B2 в качестве второй стороны (справа):

При переходе с B1 будут отображаться два отношения (FK_Left, FK_Right), но только одно из них будет содержать значение (скажем, FK_Left).

При переходе из B2 значение будет указано только в другом отношении (FK_Right). Таким образом, со стороны пользователей всегда отображаются два отношения, но это зависит от того, как была введена запись, можно ли найти данные за relation_left или relation_right . Это практически невозможно использовать.

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

Вторая основная причина: интерфейс предоставляет некоторое матричное представление, которое получает класс отношений в качестве входных данных и отображает левых партнеров в столбцах и правых партнеров в строках.

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

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

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

Комментарии:

1. это одноразовая вещь? или вы будете делать это периодически?

2. Что вы пытаетесь здесь решить? Хранение одних и тех же данных дважды … избыточно. И теперь вы заставляете каждую существующую строку указывать на ту же строку, но в обратном порядке. У этого повсюду много красных флагов. Почему бы просто не создать представление, которое «переворачивает» данные? Это было бы довольно просто с помощью инструкции update после второй вставки, но, похоже, лучшее решение здесь имеет больше смысла.

3. @sabhari Обновление старых наборов записей на одной производительной машине будет одноразовым, все новые записи будут автоматически создаваться «новым» способом

4. @SeanLange Числа в столбцах являются идентификаторами отношений к другим таблицам, и это какая-то таблица отношений m: n. Интерфейс показывает однонаправленные отношения, поэтому вам нужно начать с определенного узла (в зависимости от того, какой был введен первым), чтобы увидеть отношение. В качестве улучшения пользователи должны иметь возможность вставлять отношения двунаправленными, поэтому я хочу скопировать каждый набор. В случае удаления / модификации я могу использовать ReverseID, чтобы легко найти дубликат и сделать то же самое с дубликатом.

5. Но создание двух копий данных настолько хрупко. Это плохая идея. Создайте представление, которое вместо этого изменяет данные. Или просто измените свои соединения с этой таблицей, чтобы разрешить использование OR .

Ответ №1:

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

 create view MyReversedDataView as

select ID
    , Col1
    , Col2
from MyTable

UNION ALL

select ID
    , Col2
    , Col1
from MyTable
  

Ответ №2:

Хитрость такого рода заключается в том, чтобы начать с ВЫБОРА, который получает нужные вам данные. В этом случае вам нужен результирующий набор с Col1, Col2, reverseid.

 SELECT Col2 Col1, Col1 Col1, ID reverseid
  INTO #tmp   FROM myTable;
  

Убедите себя, что это правильно — поменялись значениями столбцов и т. Д.

Затем сделайте это:

 INSERT INTO myTable (Col1, col2, reverseid)
SELECT Col1, Col2, reverseid FROM #tmp;
  

Если вы делаете это с помощью графического интерфейса, такого как ssms, не забудьте DROP TABLE #tmp;

НО вы можете получить тот же результат с помощью чистого запроса, без дублирования строк. Почему это так?

  1. Вы экономите потраченное впустую пространство для перевернутых строк.
  2. Вы всегда получаете перевернутые строки до последней секунды, даже если вы забыли запустить процесс для их изменения и вставки в таблицу.
  3. Нет проблем с согласованностью, если вы вставляете или удаляете строки из таблицы.

Вот как вы можете это сделать.

  SELECT Col1, Col2, null reverseid FROM myTable
  UNION ALL
 SELECT Col2 Col1, Col1 Col2, ID reverseid FROM myTable;
  

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

 CREATE VIEW myTableWithReversals AS
SELECT Col1, Col2, null reverseid FROM myTable
 UNION ALL
SELECT Col2 Col1, Col1 Col2, ID reverseid FROM myTable;
  

Затем вы можете сказать SELECT * FROM myTableWithReversals WHERE Col1 = 'value' и т.д.

Комментарии:

1. ваш первый оператор выдает ошибку Column names in each table must be unique. Column name 'col1' in table '#tmp' is specified more than once. , которую я пытался использовать SELECT Col2 Col1, Col1 Col2, ID reverseid вместо этого, это то, что вы имели в виду?

2. Мои Col1 имена столбцов являются заполнителями для примера. Вы бы заменили их своими именами столбцов.

3. да, но в вашем первом кодовом блоке вы выбрали Col1 три раза, что, я думаю, не так, как предполагалось?

Ответ №3:

Позвольте мне предположить, что id столбец автоматически увеличивается. Затем вы можете сделать это в два этапа:

 insert into myTable (Col1, Col2, reverseid)
    select col2, col1, id
    from myTable t
    order by id;  -- ensures that they go in in the right order
  

При этом новые идентификаторы вставляются с правом reverseid . Теперь нам нужно обновить предыдущие значения:

 update t
    set reverseid = tr.id
    from myTable t join
         myTable tr
         on tr.reverseid = t.id;
  

Обратите внимание, что временные таблицы не нужны.

Комментарии:

1. Я не понимаю ваш последний блок кода, не могли бы вы немного объяснить это? Я получаю сообщение об ошибке tr.id The multi-part identifier "tr.id" could not be bound.

2. @mrt . . . Я добавил имя таблицы, которое вы используете, что должно устранить проблему.

3. спасибо, но, к сожалению, это не помогло, та же ошибка, даже если я вырезал все строки после tr.id

4. @mrt . . . В образце данных в вашем вопросе есть столбец с именем id . Я не знаю, почему ваш запрос не увидит его.

5. хм, может быть, я неправильно понял ваши утверждения. Изначально я думал, что t это имя вашей таблицы. Но теперь, после того, как вы вставили myTable , я в замешательстве. Если я напишу код, как вы, он почти не работает update t , потому t что неизвестно… Если я укажу myTable вместо t , произойдет сбой в tr.id . Это myTable t какая-то нотация псевдонимов? Я просто знаю table AS t