powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Объединение таблиц HELP!
14 сообщений из 14, страница 1 из 1
Объединение таблиц HELP!
    #33353480
Stepanow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!
Если не трудно, подскажите новичку в MySQL как правильно организовать решение такой задачи:

Сначала, как это уже реализовано:

Есть таблица с данными. Изначально данные берутся их таблиц Excel, VBA-скриптом я их конвертирую в формат CSV (при обычном сохранении в CSV не сохраняются некоторые особенности XLS-файла). PHP-скриптом на сервере загоняю в БД MySQL. В дальнейшем, строки таблицы пополняются новыми полями через WEB-интерфейс с участием того же PHP. Источник периодически обновляется, соответсвенно периодически база пополняется новыми данными из Экселя.

Проблема:

При обновлении приходится проверять, есть ли запись с таким названием в таблице БД и если есть, обновлять поля. Если нет - создавать. В итоге куча обращений к бд, медленная работа и оконкание тайм-лимита на выполнение PHP-скрипта. Плюс остаются "мёртвые" строки, которых уже нет в Экселе.

Что хочу:

1) Перед обновлением базы выкинуть из неё все строки, у которых пусто в "дополнительных" полях и переименовать таблицу. (чтоб потом мёртвых строк не было)
2) Заносить данные в пустую таблицу безо всяких лишних проверок.
3) "Слить" две таблицы между собой так, чтобы в строки, которые есть и там и там попали дополнительные поля (введённые через WEB-интерфейс), которых не было в экселе, а строки, которых нет в экселевских данных игнорировались.

И сделать это надо средствами MySQL, чтобы работало как можно быстрее и уложиться в тайм-лимит PHP (база приличная по объёму и если пытаться прочитать исходную базу в массив PHP, новую в другой и там с ними работать, то будет недостаточно быстро, да и памяти много уйдёт).

Буду очень признателен, если подскажете, какими SQL-командами можно это сделать. Если написал какие-то заблуждения - поправьте. Может есть другой алгоритм решения задачи...
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33353497
Фотография Валентин К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Логика работы - не зачот.
Так сделать можно, но это иррациональный путь.

Используй конструкцию load data infile для закачки cvs в пустую табличку, потом инсертить новые данные в стационарную таблицу и обновлять измененые в ёкселе строки опять же запросом, который и описыват твои условия.

Вот собственно и все.
Главное, чтобы был доступ к файлу cvs от сервера, тогда все будет сделано достаточно быстро.
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33353569
Stepanow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Валентин КЛогика работы - не зачот.
Так сделать можно, но это иррациональный путь.

Используй конструкцию load data infile для закачки cvs в пустую табличку, потом инсертить новые данные в стационарную таблицу и обновлять измененые в ёкселе строки опять же запросом, который и описыват твои условия.

Вот собственно и все.
Главное, чтобы был доступ к файлу cvs от сервера, тогда все будет сделано достаточно быстро.

Перечитал - не очень понятно выглядит.

Главный вопрос вот в чём:
Например есть таблица с колонками: "Name" "Age" "Phone" "Interests"
И есть входные данные (новая таблица из Excel), которые должны полностью переписать эту таблицу, удаляя тех людей, "Name" которых в этих данных отсутствует. Но колонки "Interests" нет в этих новых данных и его необходимо сохранить из старой таблицы.
В общем как объединить эти две таблицы, чтоб из записей в старой таблице поле "Interests" попало в новую таблицу в запись с тем же "Name". Ну и чтоб записи с именем, отсутствующим в новой таблице, никуда не копировались.

Если я буду инсертить новые данные в старую таблицу - останутся мёртвые записи - или я ошибаюсь? Я прошу написать как это сделать командами MySQL. Раньше не приходилось работать с БД и тот код, в котором приходится разбираться, написан другими людьми... В общем чувствую себя даже не чайником а самоваром :(.
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33353589
Фотография Валентин К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Stepanow
Главный вопрос вот в чём:
Например есть таблица с колонками: "Name" "Age" "Phone" "Interests"
И есть входные данные (новая таблица из Excel), которые должны полностью переписать эту таблицу, удаляя тех людей, "Name" которых в этих данных отсутствует. Но колонки "Interests" нет в этих новых данных и его необходимо сохранить из старой таблицы.
В общем как объединить эти две таблицы, чтоб из записей в старой таблице поле "Interests" попало в новую таблицу в запись с тем же "Name". Ну и чтоб записи с именем, отсутствующим в новой таблице, никуда не копировались.

У записей есть ключевые поля?
Stepanow
Если я буду инсертить новые данные в старую таблицу - останутся мёртвые записи - или я ошибаюсь? Я прошу написать как это сделать командами MySQL. Раньше не приходилось работать с БД и тот код, в котором приходится разбираться, написан другими людьми... В общем чувствую себя даже не чайником а самоваром :(.
Нет не останутся, обработать нужно будет несколькими запросми, которые соберут из 2-х таблиц одну, в которой будут учтены условия.

Кстати MySQL тут не при чем, читай про SQL тут http://www.mysql.ru/docs/gruber/
А мануал по MySQL тут http://dev.mysql.com/doc/refman/5.0/en/index.html
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33353940
Stepanow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ок, спасибо за ссылочку, сейчас почитаю. В моей книге по PHP про MySQL маловато информации.

А насчёт ключевых полей... Я не силён в терминологии, но если имеется в виду PRIMARY KEY, то в реальной программе есть ещё столбец ID с флагами AUTO_INCREMENT и PRIMARY KEY для технических нужд, поэтому в пример я его не включил. Ну а идентификация записи происходит по полю "Name".
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33364271
Stepanow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Валентин К
Используй конструкцию load data infile для закачки cvs в пустую табличку, потом инсертить новые данные в стационарную таблицу и обновлять измененые в ёкселе строки опять же запросом, который и описыват твои условия.

Вот собственно и все.
Главное, чтобы был доступ к файлу cvs от сервера, тогда все будет сделано достаточно быстро.

Как я понимаю, файл должен находиться в каталоге базы данных на сервере, а это невозможно в моём случае (обычный хостинг, где одна СУБД MySQL обслуживает много хостов). Если же файл находится на локальном компьютере, субд даже не знает о его (лок. компьютера существовании), ведь клиентом для неё является PHP, работающий на том же сервере, а не на моём компе. Как же указать размещение файла?

ЗЫ: я могу закачать файл на сервер и указать путь к нему относительно корневой для веб-сервера папки (или относительно её фактического расположения /domains/mydomain/public_html/ ) ?
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33364386
DocAl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не факт, что правильно понял проблему, но...
У вас наверняка есть какой-то столбец или их совокупность, которая однозначно определяет какую-то конкретную запись. Вероятно, в данном случае имя, или синтетический id, но факт тот, что по нему либо уже построен первичный ключ, либо есть возможность построить индекс типа UNIQUE. Про него вам лучше почитать в документации, но суть в том, что он накладывает ограничение уникальности на выбранные для него столбцы. Тем же свойством обладает и первичный ключ.
Если теперь использовать INSERT для занесения данных в таблицу, и указывать значение этих уникальных полей, в случае, если в базе уже есть запись с этим уникальным значением -- СУБД вернёт ошибку и, главное в этом случае, эта запись добавлена не будет. Чтобы СУБД не ругалась тут почём зря, используем INSERT IGNORE, что в данном случае вполне оправданно и адекватно.
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33364900
Stepanow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
DocAlНе факт, что правильно понял проблему, но...
У вас наверняка есть какой-то столбец или их совокупность, которая однозначно определяет какую-то конкретную запись. Вероятно, в данном случае имя, или синтетический id, но факт тот, что по нему либо уже построен первичный ключ, либо есть возможность построить индекс типа UNIQUE. Про него вам лучше почитать в документации, но суть в том, что он накладывает ограничение уникальности на выбранные для него столбцы. Тем же свойством обладает и первичный ключ.
Если теперь использовать INSERT для занесения данных в таблицу, и указывать значение этих уникальных полей, в случае, если в базе уже есть запись с этим уникальным значением -- СУБД вернёт ошибку и, главное в этом случае, эта запись добавлена не будет. Чтобы СУБД не ругалась тут почём зря, используем INSERT IGNORE, что в данном случае вполне оправданно и адекватно.

INSERT IGNORE, как я понял, предназначена для добавления строк, ключи которых уже есть в базе. Хорошая идея, возможно даже сохранятся нужные мне столбцы, которые есть в базе и нет в Экселе. Но мне надо одновременно и удалить данные, которых уже нет в экселе, а они тоже ведь никуда не денутся...

В общем, почитав про SQL, я понимаю решение этой задачи так:

текущая таблица называется Cur_tb и содержит поля:
name NOT NULL PRIMARY KEY, age, phone, interests. Для простоты все char(50).

-- 1. Создаю новую таблицу для новых данных.
CREATE TABLE New_tb LIKE Cur_tb;

-- 2. Загружаю данные из экселя в новую таблицу
-- (пока не разберусь с load data infile буду инсертить по-старому :-)
INSERT INTO New_tb VALUES ('Аня Пупкина', '1-9-1991', '555-55-55', NULL);
....
INSERT INTO New_tb VALUES ('Юра Ухов', '18-1-1980', '777-77-77', NULL);

-- 3. Копируем поле interests из старой таблицы в новую
UPDATE New_tb, Cur_tb SET New_tb.interests = Cur_tb.interests WHERE New_tb.name = Cur_tb.name;

-- 4. Подменяем старую таблицу новой
RENAME TABLE Cur_tb TO Old_tb, New_tb TO Cur_tb;

-- 5. Удаляем старую таблицу
DROP TABLE Old_tb;

Сейчас попробую через PhpMyAdmin проверить работоспособность "творения"...
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33365026
Stepanow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ура, работает! :)

Немного усложним задачу.
Вместо плоской базы, разобьём её на подкаталоги.
Добавляется таблица Dir_tb с полями "id" NOT NULL AUTO_INCREMENT PRIMARY KEY, ,"cat_name". Первый int, второй по традиции char(50);

А таблица с данными Cur_tb обзаводится ещё одним столбцом "cat" NOT NULL REFERENCES Dir_tb(id) - внешним ключом.

теперь надо при чтении из excel создавать ещё и New_Dir_tb, причём поля id в ней будут созданы динамически и скорее всего не совпадут с полями id Dir_tb, поэтому надо ориентироваться на поле name.

Соответственно оператор Update усложняется и в нём надо проверять не только поле name, но и поле name таблицы Dir_tb, связанное с данной записью по внешнему ключу...

Буду думать, как это реализовать, если кто знает - подскажите.
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33365324
Stepanow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сделал. Дальше ещё усложняется задача, а пока вот как решена текущая:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
-- -- -- Подготовка исходных данных -- -- --

-- Создаём таблицу каталога
CREATE TABLE Dir_tb(
id INT  NOT NULL  AUTO_INCREMENT  PRIMARY KEY,
cat_name  CHAR( 50 )  NOT NULL
)

-- Заполняем таблицу каталога
INSERT INTO Dir_tb (cat_name) VALUES ('Москва');
INSERT INTO Dir_tb (cat_name) VALUES ('Питер');
INSERT INTO Dir_tb (cat_name) VALUES ('Уфа');

-- Создаём основную таблицу
CREATE TABLE Cur_tb(
name  CHAR( 50 )  NOT NULL  PRIMARY KEY,
cat INT  NOT NULL REFERENCES Dir_tb(id),
age  CHAR( 50 ),
phone  CHAR( 50 ),
interests  CHAR( 50 )
)

-- Заполняем основную таблицу
INSERT INTO Cur_tb VALUES ('Аня Пупкина', 3 ,'20','123456','Музыка');
INSERT INTO Cur_tb VALUES ('Ваня Пупкин', 3 ,'23','123456','Поп-музыка');
INSERT INTO Cur_tb VALUES ('Галя Иванова', 1 ,'18','8765498','Цветы');
INSERT INTO Cur_tb VALUES ('Дима Билайн', 1 ,'30','федеральный','Музычка');
INSERT INTO Cur_tb VALUES ('Владимир Путин', 2 ,'50','1111111','системы управления государством');
INSERT INTO Cur_tb VALUES ('Пит Смирнофф', 2 ,'30','8765423','Алкоголь');
INSERT INTO Cur_tb VALUES ('Евгений Кутежников', 1 ,'26','4327583','Алкоголь');
INSERT INTO Cur_tb VALUES ('Витя Монин', 1 ,'12','9736734','Деньги');
INSERT INTO Cur_tb VALUES ('Ли Цинь', 1 ,'21','654321','Торговля безделушками');

-- -- -- Исходные данные готовы -- -- --

-- -- -- Приступаем к обновлению базы -- -- --

-- -- 1. Создаём таблицы под новые данные

-- 1.1 Создаём новую таблицу каталога
CREATE TABLE New_Dir_tb LIKE Dir_tb;

-- 1.2 Создаём новую основную таблицу
CREATE TABLE New_tb LIKE Cur_tb;

-- -- 2. Заносим новые данные в таблицы

-- 1.1.2 Заполняем новую таблицу каталога
INSERT INTO New_Dir_tb (cat_name) VALUES ('Москва');
INSERT INTO New_Dir_tb (cat_name) VALUES ('Питер');
INSERT INTO New_Dir_tb (cat_name) VALUES ('Сочи');

-- 1.2.2 Заполняем новую основную таблицу
INSERT INTO New_tb VALUES ('Алик Хачикян', 3 ,'35','234566',NULL);
INSERT INTO New_tb VALUES ('Дима Билайн', 1 ,'30','федеральный',NULL);
INSERT INTO New_tb VALUES ('Владимир Путин', 2 ,'50','1111111',NULL);
INSERT INTO New_tb VALUES ('Пит Смирнофф', 2 ,'30','8765423',NULL);
INSERT INTO New_tb VALUES ('Евгений Кутежников', 1 ,'26','4327583',NULL);
INSERT INTO New_tb VALUES ('Витя Монин', 1 ,'12','9736734',NULL);
INSERT INTO New_tb VALUES ('Ли Цинь', 1 ,'21','654321',NULL);

-- -- 3. Копируем поле interests из старой таблицы в новую
UPDATE New_tb, Cur_tb, New_Dir_tb, Dir_tb 
SET New_tb.interests = Cur_tb.interests 
WHERE New_tb.name = Cur_tb.name 
AND New_tb.cat = New_Dir_tb.id
AND Cur_tb.cat = Dir_tb.id
AND Dir_tb.cat_name = New_Dir_tb.cat_name;
-- Уф :)

-- -- 4. Подменяем старые таблицы новыми
RENAME TABLE Cur_tb TO Old_tb, New_tb TO Cur_tb, Dir_tb TO Old_Dir_tb, New_Dir_tb TO Dir_tb;

-- 5. Удаляем старые таблицы
DROP TABLE Old_tb, Old_Dir_tb;

А теперь слабо написать оператор UPDATE взамен моего, который справился бы со следующей задачей ?:
Вместо каталогов первого уровня, как в предыдущем примере, появляется дерево каталогов. Вложенность достигается добавлением ещё одной колонки в таблице Dir_tb. Эта колонка называется cat (или как-то ещё, если для алгоритма будет вредно совпадение с одноимённым полем основной таблицы Cur_tb) и содержит id родительского каталога по отношению к текущему, или NULL, если это корневой каталог. Возможно что она REFERENCES Dir_tb(id), но я не знаю, как сделать тогда в ней NULL, ведь поле id NOT NULL. В общем надо как-то пройтись по дереву каталогов до нуля, сравнивая при этом поля cat_name.

Возможно ли это в принципе одним запросом к базе сделать?
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33365335
Stepanow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Или проще на этапе ввода таблицы каталога присваивать каталогам id из старой таблицы каталога (если такие записи там есть), сравнивая имена и родительские id, и иметь потом возможность сравнивать старую таблицу с новой, не вытаскивая поля с именами и именами каталога а опирась только на id?

На этапе ввода данных это очевидно медленнее, а на этапе UPDATE - должно быть быстее... Какой алгоритм предпочесть?

ЗЫ: В экселе, понятное дело, никаких ID нет, их приходится формировать при вводе строки в базу.
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33366558
Фотография Валентин К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
StepanowИли проще на этапе ввода таблицы каталога присваивать каталогам id из старой таблицы каталога (если такие записи там есть), сравнивая имена и родительские id, и иметь потом возможность сравнивать старую таблицу с новой, не вытаскивая поля с именами и именами каталога а опирась только на id?

На этапе ввода данных это очевидно медленнее, а на этапе UPDATE - должно быть быстее... Какой алгоритм предпочесть?

ЗЫ: В экселе, понятное дело, никаких ID нет, их приходится формировать при вводе строки в базу.

Насколько я понял из сырцов команд ключом для людей является поле name, вот по нему и сравнивай в update, по нему можно легко отобрать и регионы, если нужно.
update пиши аккуратно и пробуй только на тестовой копии.
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33370102
Stepanow
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А вот такой вопрос: Можно ли при инсерте в одну базу одновременно выполнять выборку из другой отдельных столбцов и инсертить их вместе с остальными данными?
...
Рейтинг: 0 / 0
Объединение таблиц HELP!
    #33374465
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да
------------------
- А как в Интеpнете pаботать? - Сначала нужно узнать, что вам нужно rtfm
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Объединение таблиц HELP!
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]