Tomsk Sysadmins Forum
Windows => Программирование => Topic started 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 = 'Сибирь'
здесь запрос уже ничего не возвращает. Я так понимаю, что он находит строки где банк = Урал и потом в них же ищет по второму условию и ничего не находит.
Как же мне написать, чтобы были только те люди, которые одновременно удовлетворяют обоим условиям??
-
Если одному человеку может соответствовать несколько банков, не проще ли организовать два отношения - люди и банки - а между ними организовать связь один-ко-многим?
Почитайте теорию реляционных баз данных.
-
Есть таблица Peoples с полем bank. Т.е. у людей могут быть задолженности в разных банках. Допустим мне нужно узнать у каких людей задолженность сразу в двух банках(Урал и Сибирь).
SELECT full_name, COUNT(full_name) AS bank_cnt
FROM people
GROUP BY full_name
HAVING (COUNT(full_name) > 1)
покажет у кого больше одной задолженности.
P.S. full_name - поле с Ф.И.О.
-
Если одному человеку может соответствовать несколько банков, не проще ли организовать два отношения - люди и банки - а между ними организовать связь один-ко-многим?
Т.е. создать две таблицы? И напротив каждого человека писать 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;
И если вводишь поиск по одному банку, то все нормально, а если написать другой, то ничего не найдет.
Параметров для поиска на самом деле больше
-
Точнее не один-ко-многим, а многие-ко-многим. Например:
-- таблица людей
CREATE TABLE peoples (
ID INTEGER,
Full_name VARCHAR(30),
City VARCHAR(30),
...,
PRIMARY KEY (ID)
);
-- таблица банков
CREATE TABLE banks (
ID INTEGER,
Name VARCHAR(30),
...,
PRIMARY KEY (ID)
);
-- таблица долгов
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)
);
Например, нужен человек у которого задолженность в банке Урал, задолженность более 50000, который проживает в Томске, и чтобы у этого человека была задолженность в банке Сибирь менее 40000
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 = 'Сибирь')
)
и т.п.
-
...
Как же мне написать, чтобы были только те люди, которые одновременно удовлетворяют обоим условиям??
Вот текст необходимого запроса, и не надо заморачиваться со множеством таблиц.
select * from peoples where bank = 'Урал' and fio in (select fio from peoples where bank = 'Сибирь')
-
Всем огромное спасибо. Следуя совету vak у меня все получилось. Но другие советы тоже пригодятся.
-
А если кто-то опечатается?
Всётаки думаю идея с несколькими таблицами правильна.
-
У меня можно выбирать из выпадающего списка условия поиска. Сам ввести ничего не можешь
-
Так и места в базе меньше занимать будет. Да и вообще хоть правила нормализации будут соблюдаться я полагаю.
-
Да, спасибо. В конечном итоге я переделал, как мне посоветовал sie. Со временем понял, что так будет правильнее
-
Есть таблица 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 = 'Сибирь')