#sql #sqlite
Вопрос:
Я пытаюсь создать своего рода мусорное ведро. Когда я удаляю столбец из таблицы, я помещаю все данные из него в специальную таблицу, называемую bin. Позже я хочу иметь возможность восстановить этот столбец и добавить его в существующую таблицу со случайными данными и произвольного размера.
Пример:
У меня есть две таблицы, которые выглядят так:
Таблица 1 бункер
| columnA | columnB | | origin | columnC | columnD |
| ------- | ------- | | ------- | ------- | ------- |
| aa | 10 | | columnD | NULL | a |
| bb | 20 | | columnD | NULL | s |
| cc | 30 | | columnD | NULL | d |
| columnD | NULL | f |
| columnC | 100 | NULL |
| columnC | 200 | NULL |
Теперь я хочу добавить столбец, например ColumnC или ColumnD, из таблицы bin в таблицу 1, как это:
| columnA | columnB | columnC |
| ------- | ------- | ------- |
| aa | 10 | 100 |
| bb | 20 | 200 |
| cc | 30 | NULL |
| columnA | columnB | columnD |
| ------- | ------- | ------- |
| aa | 10 | a |
| bb | 20 | s |
| cc | 30 | d |
| NULL | NULL | f |
| columnA | columnB | columnC | columnD |
| ------- | ------- | ------- | ------- |
| aa | 10 | 100 | a |
| bb | 20 | 200 | s |
| cc | 30 | NULL | d |
| NULL | NULL | NULL | f |
Я использую Python и Sqlite 3.31.1, хотя я открыт для изменения версии, которую я использую, так как некоторые люди предположили, что эта версия не допускает операций объединения, так что пусть это не будет помехой.
Я знаю, что могу извлечь столбец из корзины следующим образом:
SELECT columnC
FROM bin
WHERE origin='columnC'
Но я не знаю, как вставить этот столбец, начиная с его первой записи, в другую таблицу, а остальные заполнить пустыми записями.
Комментарии:
1. Почему в столбце b меняются значения в третьей строке?
2. Какова ваша версия SQLite?
3. Как бы вы определили, что значение 100 в столбце должно сопровождаться aa в столбце
4. В основном только по номеру строки. Я хочу заполнить столбец, который я получаю из таблицы bin по порядку, в новый столбец в другой таблице.
5. @Obnidem Меня смущает тот факт, что ваш вопрос имеет два голоса «против» и ни одного голоса «за». Мне это кажется разумным вопросом, и, по-видимому, многие в сообществе согласны с этим, поскольку люди вступают в разговор с пояснительными комментариями и ответами. Я собираюсь поднять ваш вопрос, и я надеюсь, что ответчики и другие тоже это сделают. Добро пожаловать в сообщество.
Ответ №1:
Один из способов определить, из какой строки bin
вы выберете значение columnC
для обновления каждой строки table1
, — это использовать 2 коррелированных подзапроса, которые подсчитывают количество строк в каждой таблице с rowid
меньшим, чем текущее rowid
:
UPDATE table1 AS t1
SET columnC = (
SELECT b1.columnC
FROM bin AS b1
WHERE (SELECT COUNT(*) FROM bin b2 WHERE b2.rowid < b1.rowid) =
(SELECT COUNT(*) FROM table1 t2 WHERE t2.rowid < t1.rowid)
)
Это решение может быть не самым эффективным для большого набора данных, но используемая вами версия SQLite не поддерживает объединения, которые будут работать лучше.
Смотрите демонстрацию.
Комментарии:
1. Это близко к истине, но работает не совсем так, как задумывалось. Я добавил еще два примера, чтобы еще больше проиллюстрировать, что я хочу сделать.
2. @Obnidem этот запрос отвечает на вопрос, как вы его опубликовали, если у вас есть новое требование, вы можете задать новый вопрос.
Ответ №2:
Я придумал решение, которое требует полного внешнего соединения, которое недоступно в sqlite, но может быть смоделировано с помощью двух последовательных левых соединений и объединения всех.
Полное Внешнее Соединение:
SELECT A.columnA, A.columnB, B.columnC
FROM
(SELECT columnA, columnB, row_number() OVER (ORDER BY (SELECT 0))
AS rc FROM table1)A
FULL OUTER JOIN
(SELECT columnC, row_number() OVER (ORDER BY (SELECT 0))
AS rc FROM (SELECT columnC FROM bin WHERE origin='columnC'))B
ON A.rc = B.rc
Два Левых Объединения и Объединение Всех:
SELECT A.columnA, A.columnB, B.columnC
FROM
(SELECT columnA, columnB, row_number() OVER (ORDER BY (SELECT 0))
AS rc FROM table1)A
LEFT JOIN
(SELECT columnC, row_number() OVER (ORDER BY (SELECT 0))
AS rc FROM (SELECT columnC FROM bin WHERE origin='columnC'))B
ON A.rc = B.rc
UNION ALL
SELECT A.columnA, A.columnB, B.columnC
FROM
(SELECT columnC, row_number() OVER (ORDER BY (SELECT 0))
AS rc FROM (SELECT columnC FROM bin WHERE origin='columnC'))B
LEFT JOIN
(SELECT columnA, columnB, row_number() OVER (ORDER BY (SELECT 0))
AS rc FROM table1)A
ON A.rc = B.rc
WHERE A.rc IS NULL;