Tomsk Sysadmins Forum

Windows => Программирование => Topic started by: blackmask on August 02, 2008, 21:13:50

Title: Не могу составить запрос
Post by: blackmask on August 02, 2008, 21:13:50
Есть таблица Peoples с полем bank. Т.е. у людей могут быть задолженности в разных банках. Допустим мне нужно узнать у каких людей задолженность сразу в двух банках(Урал и Сибирь).
написал запрос
select * from peoples
where bank = 'Урал' or bank = 'Сибирь'
Как и следовало ожидать он мне вернул людей у которых задолженность только в Урале, только в Сибири, а тех людей у которых и там и здесь вернул 2 раза.

написал:
select * from peoples
where bank = 'Урал' and bank = 'Сибирь'
здесь запрос уже ничего не возвращает. Я так понимаю, что он находит строки где банк = Урал и потом в них же ищет по второму условию и ничего не находит.

Как же мне написать, чтобы были только те люди, которые одновременно удовлетворяют обоим условиям??
Title: Не могу составить запрос
Post by: sie on August 02, 2008, 21:29:23
Если одному человеку может соответствовать несколько банков, не проще ли организовать два отношения - люди и банки - а между ними организовать связь один-ко-многим?
Почитайте теорию реляционных баз данных.
Title: Не могу составить запрос
Post by: visual on August 02, 2008, 22:49:01
Quote from: blackmask
Есть таблица Peoples с полем bank. Т.е. у людей могут быть задолженности в разных банках. Допустим мне нужно узнать у каких людей задолженность сразу в двух банках(Урал и Сибирь).
Code: [Select]
SELECT full_name, COUNT(full_name) AS bank_cnt
FROM people
GROUP BY full_name
HAVING (COUNT(full_name) > 1)
покажет у кого больше одной задолженности.
P.S. full_name - поле с Ф.И.О.
Title: Не могу составить запрос
Post by: blackmask on August 03, 2008, 20:45:07
Quote from: sie
Если одному человеку может соответствовать несколько банков, не проще ли организовать два отношения - люди и банки - а между ними организовать связь один-ко-многим?
Т.е. создать две таблицы? И напротив каждого человека писать ID банка и наоборот?
Поиск на самом деле будет не по двум параметрам, это я для простоты написал. Например, нужен человек у которого задолженность в банке Урал, задолженность более 50000, который проживает в Томске, и чтобы у этого человека была задолженность в банке Сибирь менее 40000
И так далее

Вот код на делфи с помощью которого можно искать человека у которого задолженность в банке более допустим 40000 и менее 60000

DataModule2.FindQuery.Active := false;
DataModule2.FindQuery.SQL.Clear;
DataModule2.FindQuery.SQL.Add('select * from peoples');
DataModule2.FindQuery.SQL.Add('where bank = '''+StringGrid1.Cells[0,1]+'''');   //Параметры для поиска вводятся в StringGrid
for i := 1 to AddFindForm.Row do begin                                                            //AddFindForm.Row - это количество заполненных полей для поиска
  if i <> 1 then
    DataModule2.FindQuery.SQL.Add('and bank = '''+StringGrid1.Cells[0,i]+'''');                                  //В нулевом поле выбирается банк
  DataModule2.FindQuery.SQL.Add('and minvalue '+StringGrid1.Cells[2,i]+' '+StringGrid1.Cells[3,i]);  // Во 2 поле условие(<,>,=) в 3 - сумма задолженности
end;

  DataModule2.FindQuery.Active := true;

И если вводишь поиск по одному банку, то все нормально, а если написать другой, то ничего не найдет.
Параметров для поиска на самом деле больше
Title: Не могу составить запрос
Post by: sie on August 04, 2008, 00:07:48
Точнее не один-ко-многим, а многие-ко-многим. Например:

-- таблица людей
Code: [Select]
CREATE TABLE peoples (
 ID INTEGER,
 Full_name VARCHAR(30),
 City VARCHAR(30),
 ...,
 PRIMARY KEY (ID)
);
-- таблица банков
Code: [Select]
CREATE TABLE banks (
ID INTEGER,
Name VARCHAR(30),
...,
PRIMARY KEY (ID)
);
-- таблица долгов
Code: [Select]
CREATE TABLE dolgi (
PeopleID INTEGER,
BankID INTEGER,
Value DOUBLE PRECISION,
...,
PRIMARY KEY (PeopleID, BankID),
FOREIGN KEY (PeopleID) REFERENCES peoples (ID),
FOREIGN KEY (BankID) REFERENCES banks (ID)
);
Quote from: blackmask
Например, нужен человек у которого задолженность в банке Урал, задолженность более 50000, который проживает в Томске, и чтобы у этого человека была задолженность в банке Сибирь менее 40000
Code: [Select]
SELECT p.Full_name
FROM peoples p
WHERE (p.City = 'Томск') AND p.ID IN (
SELECT d.PeopleID
FROM dolgi d
LEFT JOIN banks b ON b.ID = d.BankID
WHERE (d.Value > 50000) AND (b.Name = 'Урал')
) AND p.ID IN (
SELECT d.PeopleID
FROM dolgi d
LEFT JOIN banks b ON b.ID = d.BankID
WHERE (d.Value < 40000) AND (b.Name = 'Сибирь')
)
и т.п.
Title: Не могу составить запрос
Post by: vak on August 04, 2008, 09:14:22
Quote from: blackmask
...

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

select * from peoples where bank = 'Урал' and fio in (select fio from peoples where bank = 'Сибирь')
Title: Не могу составить запрос
Post by: blackmask on August 04, 2008, 18:13:47
Всем огромное спасибо. Следуя совету vak у меня все получилось. Но другие советы тоже пригодятся.
Title: Не могу составить запрос
Post by: CRonaldo on August 06, 2008, 15:15:45
А если кто-то опечатается?  
Всётаки думаю идея с несколькими таблицами правильна.
Title: Не могу составить запрос
Post by: blackmask on August 07, 2008, 16:06:12
У меня можно выбирать из выпадающего списка условия поиска. Сам ввести ничего не можешь
Title: Не могу составить запрос
Post by: CRonaldo on August 15, 2008, 11:40:16
Так и места в базе меньше занимать будет. Да и вообще хоть правила нормализации будут соблюдаться я полагаю.
Title: Не могу составить запрос
Post by: blackmask on September 08, 2008, 18:57:00
Да, спасибо. В конечном итоге я переделал, как мне посоветовал sie. Со временем понял, что так будет правильнее
Title: Не могу составить запрос
Post by: FireWall on September 23, 2008, 08:28:16
Quote from: blackmask
Есть таблица Peoples с полем bank. Т.е. у людей могут быть задолженности в разных банках. Допустим мне нужно узнать у каких людей задолженность сразу в двух банках(Урал и Сибирь).
написал запрос
select * from peoples
where bank = 'Урал' or bank = 'Сибирь'
Как и следовало ожидать он мне вернул людей у которых задолженность только в Урале, только в Сибири, а тех людей у которых и там и здесь вернул 2 раза.

написал:
select * from peoples
where bank = 'Урал' and bank = 'Сибирь'
здесь запрос уже ничего не возвращает. Я так понимаю, что он находит строки где банк = Урал и потом в них же ищет по второму условию и ничего не находит.

Как же мне написать, чтобы были только те люди, которые одновременно удовлетворяют обоим условиям??

ммм, проверить нет возможности, но возможно:
select ID_user, FIO, Summa_Zadolzhnosti from peoples where bank = 'Урал'  and ID_user in (select ID_user from peoples where bank = 'Сибирь')