Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 18.01.2012, 13:06   #1
SovereignSun
Форумчанин
 
Регистрация: 22.11.2011
Сообщений: 127
По умолчанию Перебор в массиве с выявлением совпадений

Здраствуйте, у меня трудная задача которую не могу решить.
Есть три базы данных (MS SQL 2008), в базах данных есть таблицы в которых есть поле Договор. Но одна база данных пустая (Прил.dbo)
Так вот.. в чем задача перед открытием AdoQuery с базой данных нужно из первой базы данных сохранить столбец Договор в массив, потом сохранить значения из столбца Договор в базе данных Прил.dbo, потом сравнить их на наличие одинаковых и разных значений, и те что нет закинуть в столбец Договор в базе данных Прил.dbo, при первом запуске закинуть все значения построчно. Потом в столбец BD базы данных Прил.dbo закинуть наименование первой базы данных как string. Потом загрузить первую базу данных с полем Отметка из базы данных Прил.dbo как right join к первой базе данных, c
right join Прил.dbo.TBL ON Прил.dbo.TBL.Договор=tablename.dbo. Договора.Договор
where Прил.dbo.TBL.BD=tablename
и открыть первую базу данных, и также делать при открытии второй базы данных, кнопки у меня есть.

Привожу часть кода с комментарием:
Код:
//Открытие базы данных Розн_23
//db_name (string)
procedure TForm1.N6Click(Sender: TObject);
begin
qry1.Close;
qry2.Close;
qry3.Close;
db_name:='Розн_23';
qry4.SQL.Clear;
qry4.SQL.Text:='Select * from '+db_name+'.dbo.Договора';
qry4.Open;
qry1.SQL.Text:='Select distinct CAST((CASE WHEN CHARINDEX('+chr(39)+'-'+chr(39)+','+db_name+'.dbo.Договора.Договор)>0 '+
'THEN RIGHT('+db_name+'.dbo.Договора.Договор,LEN('+db_name+'.dbo.Договора.Договор)-CHARINDEX('+chr(39)+'-'+chr(39)+','+db_name+'.dbo.Договора.Договор)) '+
'ELSE NULL END) AS varchar(20)) AS ID, Организация From '+db_name+'.dbo.Счета '+
'Left join '+db_name+'.dbo.Договора ON '+db_name+'.dbo.Счета.Договор='+db_name+'.dbo.Договора.Договор';
qry2.SQL.Text:='Select * from '+db_name+'.dbo.Договора '+
'Left join '+db_name+'.dbo.Счета ON '+db_name+'.dbo.Договора.Договор='+db_name+'.dbo.Счета.Договор';
qry3.SQL.Text:='Select * From '+db_name+'.dbo.Пользователи';
Form2.qry1.Close;
Form2.qry1.SQL.Text:='Select * from LD_'+db_name+'.dbo.LD_Пользователи';
//ShowMessage(qry1.SQL.Text);
qry1.Open;
Form2.qry1.Open;
end;
Отсюда в qry2 мне и нужно дописать код:
собственно такой:
Код:
Select * from Розн_23.dbo.Договора
Left join Розн_23.dbo.Счета ON Розн_23.dbo.Договора.Договор=Розн_23.dbo.Счета.Договор
right join Прил.dbo.TBL ON Прил.dbo.TBL.Договор=Розн_23.dbo.Счета.Договор
where Прил.dbo.TBL.BD=Розн_23
в коде он у меня так.
Код:
qry2.SQL.Text:='Select * from '+db_name+'.dbo.Договора '+
'Left join '+db_name+'.dbo.Счета ON '+db_name+'.dbo.Договора.Договор='+db_name+'.dbo.Счета.Договор'+
'Right join Прил.dbo.TBL ON Прил.dbl.TBL.Договор='+db_name+'.dbo.Договора.Договор where Прил.dbo.TBL.BD='+db_name;
Что еще необходимо уточнить?



___________
Код нужно оформлять по правилам:
тегом [CODE]..[/СODE] (это кнопочка с решёточкой #)
Не забывайте об этом!
Модератор.

Последний раз редактировалось Serge_Bliznykov; 18.01.2012 в 13:42.
SovereignSun вне форума Ответить с цитированием
Старый 18.01.2012, 14:13   #2
rdama
Форумчанин
 
Аватар для rdama
 
Регистрация: 25.07.2009
Сообщений: 533
По умолчанию

А на уровне сервера БД это сделать нельзя что ли?
Из 2-х бд собрать выборку и закинуть в 3-ю.
Нафига делфи для этого дергать?
Маразм крепчал. Еноты пели...
R-style Dataknowlege Access Member Account (RDAMA)
rdama вне форума Ответить с цитированием
Старый 18.01.2012, 15:00   #3
SovereignSun
Форумчанин
 
Регистрация: 22.11.2011
Сообщений: 127
По умолчанию

Цитата:
Сообщение от rdama Посмотреть сообщение
А на уровне сервера БД это сделать нельзя что ли?
Из 2-х бд собрать выборку и закинуть в 3-ю.
Нафига делфи для этого дергать?
Задача такая потому-что, база данных стоит на сервере далеко, подключение к ней через интернет, следить за выборками и делать их никто не будет, поэтому в моей программе пришлось все это делать, в которой при нажатии на кнопку например, Открыть Базу Розн_23 открывает вся это выборка и много операций выполняется. чтобы в конце концов в последнем Query выдать нужные данные. Вот в чем проблема.

Сейчас уже сделал половину вопроса сам. осталась проблема не могу понять как это сделать, вот код:
Код:
procedure TForm1.N6Click(Sender: TObject);
var  i,j: integer;
     first_mass: array [0..9999] of string;
     second_mass: array [0..9999] of string;
     last_k: Integer;
begin
qry1.Close;
qry2.Close;
qry3.Close;
db_name:='Розн_23';
//Выборка из Розн_23
qry4.SQL.Clear;
qry4.SQL.Text:='Select Договор from '+db_name+'.dbo.Договора Order by Договор';
qry4.Open;
qry4.First;
//Количество записей
last_k:=qry4.RecordCount;
//Запись в массив 1
i:=0;
for i:=i+1 to qry4.RecordCount do
begin
first_mass[i]:=qry4.FieldByName('Договор').Asstring;
qry4.RecNo:=qry4.RecNo+1;
end;
//Проверка
ShowMessage(first_mass[1]+' '+first_mass[2]+' '+first_mass[3]+' '+first_mass[4]+' ');
//Выборка из Прил.dbo
qry4.SQL.Clear;
qry4.SQL.Text:='Select * from Прил.dbo.TBL Order by Договор';
qry4.Open;
qry4.First;
//Запись в массив 2
j:=0;
for j:=j+1 to qry4.RecordCount do
begin
second_mass[j]:=qry4.FieldByName('Договор').Asstring;
qry4.RecNo:=qry4.RecNo+1;
end;
//Проверка
ShowMessage(second_mass[1]+' '+second_mass[2]+' '+second_mass[3]+' '+second_mass[4]+' ');
i:=0;
// Удалить записи если что-то не так (тесты)
{for i:=i+1 to last_k do
    begin qry4.Delete;
      qry4.Next;
    end; }
Запись из массива 1 в базу данных Прил.dbo каждую запись.
if qry4.IsEmpty=True then
for i:=i+1 to last_k do
    begin qry4.Append;
      qry4.FieldByName('Договор').AsString:=first_mass[i];
      qry4.FieldByName('БД').AsString:=db_name;
      qry4.Next;
    end;
end;
1. Как сделать динамический массив? что-то я не помню... не получается
2. Как сделать чтобы данные из первого и второго массива проверялись на повторы и закидывать все в третий массив? Например:

Первый массив | Второй массив
1-----------------1
2-----------------2
3-----------------3
4-----------------5
5-----------------6
6-----------------7
7-----------------8
8-----------------1
9-----------------10
10-----------------11
11
12
13

Вот чтобы те которые есть в первом массиве не копировались в третий массив, а те которых нет копировались. (Массив array of string)?
SovereignSun вне форума Ответить с цитированием
Старый 18.01.2012, 15:24   #4
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

SovereignSun, вам правильно говорят, что когда Вы пишите запрос, которые затрагивает НЕСКОЛЬКО таблиц, то это запрос выполняется на самом сервере (ну, я имею в виду нормальные СУБД).
это по сути.

теперь же формальные ответы на ваши вопросы (которые не нужно решать, если сделать всё запросами):
Цитата:
1. Как сделать динамический массив? что-то я не помню... не получается
var ИмяМассива : array of НужныйТип;
...
SetLength(ИмяМассива, КоличествоЭлементов);

Цитата:
Как сделать чтобы данные из первого и второго массива проверялись на повторы и закидывать все в третий массив?
берём первую запись - ищем её во втором массиве (перебором). нашли - ничего не делаем, если не нашли - копируем куда надо.
можно улучшить быстродействие, если использовать отсортированные структуры.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 18.01.2012, 15:30   #5
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
Вот чтобы те которые есть в первом массиве не копировались в третий массив, а те которых нет копировались.
Массивы отсортированы? Если да, то берем алгоритм сортировки слиянием и исправляем под себя ( из трех возможных вариантов = > < добавление делаем только в одном случае).

Код:
i:=0; j:=0; k:=0;
while i<length(m1) and (j<length(m2) do begin
   if m1[i]=m2[j] then begin//совпадение 
        i:=i+1; j:=j+1; //пропускаем оба 
   end else if m1[j]>m2[j] then begin // в M2 еще можно найти
       i:=i+1; // меняем индекс M2 
   end else if m1[i]<m2[j] then begin // в M2 точно нет
       M3[k]:=M1[i]; k:=k+1; // добавляем
       i:=i+1; //сдвигаем первый(M1)
  end else reise EXception.Create('НЕВОЗМОЖНОЕ ВОЗМОЖНО!');
end;
for j:=i to length(m1)-1 do begin
  m3[k]:=m1[j]; k:=k+1;
end;  // добавить все то что не успели проверить 
end;
Данный алгоритм будет работать для ЧИСЛОВОГО сравнения!
Цитата:
(Массив array of string)?
поскольку 12>2 (как числа) НО '12'<'2' (как строки).

можно использовать и сравнение строк, но и исходные массивы должны быть отсортированы по этому правилу (сравнение строк).
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 18.01.2012 в 15:37.
evg_m вне форума Ответить с цитированием
Старый 18.01.2012, 15:53   #6
SovereignSun
Форумчанин
 
Регистрация: 22.11.2011
Сообщений: 127
По умолчанию

Блин вот логически составил код.. а нефига...
Код:
i:=0;
j:=0;
k:=0;
// last_k - последняя запись в первом массиве
for i:=i+1 to last_k do
begin
if first_mass[i]<>second_mass[j] then
// last_j - последняя запись во втором массиве
for j:=j+1 to last_j do
begin
  if first_mass[i]<>second_mass[j] then
  begin
  third_mass[k]:=first_mass[i];
  k:=k+1;
  end;
end;
end;
SovereignSun вне форума Ответить с цитированием
Старый 18.01.2012, 16:00   #7
SovereignSun
Форумчанин
 
Регистрация: 22.11.2011
Сообщений: 127
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
SovereignSun,
var ИмяМассива : array of НужныйТип;
...
SetLength(ИмяМассива, КоличествоЭлементов);
Сделал такой массив, выскакивает ошибка приложения.
SovereignSun вне форума Ответить с цитированием
Старый 18.01.2012, 18:26   #8
rdama
Форумчанин
 
Аватар для rdama
 
Регистрация: 25.07.2009
Сообщений: 533
По умолчанию

Задача у вас просто несколько дурная.
Сам работаю в компании с сетью по всей стране. И такой дурости не видел.
Правда не мс у нас под капотом оракл.
Но и мс умеет с дблинками работать, только работа несколько иначе строится.
И данные синхронизируются и выгружаются в обе стороны без всяких проблем.
Да бывают проблемы на стороне провов. Особенно с такими регионами как Камчатка где из связи только спутник, но ничего и это не страшно.
А то что у вас никто не следит за БД так это извините, глупо как раз с вашей стороны.
У вас получается БД живет своей жизнью, а все остальное своей.
При этом вы пытаетесь исправлять на клиенте, то что надо исправить на сервере.
Это исходя из ваших слов о том, что
Цитата:
поэтому в моей программе пришлось все это делать, в которой при нажатии на кнопку например, Открыть Базу Розн_23 открывает вся это выборка и много операций выполняется
Просто не понятно зачем усложнять там где можно упростить.
А то что интернет, так это не страшно.
До этого работал над системой БД которой крутилась на ВПС в США, а клиентами были суда по всему миру.
И ничего не пугал никого нестабильный спутниковый канал с огромным пингом.
Код:
SELECT ...
FROM ...
INNER JOIN LinkedServerName.DatabaseName.ObjectOwner.ObjectName
ON ...
Маразм крепчал. Еноты пели...
R-style Dataknowlege Access Member Account (RDAMA)
rdama вне форума Ответить с цитированием
Старый 19.01.2012, 09:14   #9
SovereignSun
Форумчанин
 
Регистрация: 22.11.2011
Сообщений: 127
По умолчанию

Ребята я все понимаю, но это не помогает мне решить задачу... не моя проблема, что в организации никто за базой не следит, и кажый день не будет такую проверку делать и копировать ID из одной базы в другую. Просто в одной базе хранятся данные, которые из сайта закидываются.. а во второй базе изменения которые необходимы пользователям в организации.. (галочки, поле комментария).. и надо только их сохранять без изменений в отдельной базе по привязке ID (Договор), БД (База Данных).
Как сделать цикл внутри цикла с проверкой?
Тоесть цикл по первому массиву, внутри цикл по второму циклы на случай если = то следующий элемент первого цикла, если не равен и запись второго цикла последняя, то добавить запись из первого цикла в третий. ????
SovereignSun вне форума Ответить с цитированием
Старый 19.01.2012, 10:01   #10
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
Блин вот логически составил код.. а нефига...
с логикой есть проблемы
Код:
    if first_mass[i] <> second_mass[j] then begin // записываем любой несовпавший ??? 
а такой всегда найдется не первый так второй, где здесь логика!
      third_mass[k]:=first_mass[i];
      k:=k+1;
      break; // после того как записали нам больше нечего здесь делать 
    end;
надо просмотреть (сравнить) ВЕСЬ второй массив и если нет ни одного совпадения то только тогда записывть.
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 19.01.2012 в 10:04.
evg_m вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поиск совпадений KillJoy Паскаль, Turbo Pascal, PascalABC.NET 2 05.09.2011 11:53
Поиск совпадений Серёга0629 Microsoft Office Excel 9 29.08.2011 09:22
Поиск совпадений Claster Общие вопросы Delphi 4 22.06.2011 17:34
Поиск совпадений в БД _PROGRAMM_ PHP 6 21.05.2010 13:53
Поиск совпадений ячейки в массиве VPavlov Microsoft Office Excel 1 02.04.2010 19:29