SQL заявка
16 отговора
512 прегледа
SQL заявка
Колеги бихте ли ми помогнали за една SQL заявка
Имам колона ЕГН и две цифри от до /от години God1 до годиниGod2/.
Как да напиша заявката, че да ми извади резултата всички егенета от примерно всички ЕГН - та отговарящи на God1 >= Егн =<God2тази заявка.
Много съм на зор. Помагайте.
Имам колона ЕГН и две цифри от до /от години God1 до годиниGod2/.
Как да напиша заявката, че да ми извади резултата всички егенета от примерно всички ЕГН - та отговарящи на God1 >= Егн =<God2тази заявка.
Много съм на зор. Помагайте.
Re: SQL заявка
Примерно
SELECT * FROM [таблицата ти] WHERE
(EGN >= :God1) AND (EGN <= :God2)
Ако правиш приложение на Делфи, можеш да ползваш параметри на query-то, за да предадеш годините (затова са двете точки пред God1 и God2). Можеш и без параметри, просто като си конструираш стринг(ове), който после да присвоиш на SQL пропъртито на query-то.
SELECT * FROM [таблицата ти] WHERE
(EGN >= :God1) AND (EGN <= :God2)
Ако правиш приложение на Делфи, можеш да ползваш параметри на query-то, за да предадеш годините (затова са двете точки пред God1 и God2). Можеш и без параметри, просто като си конструираш стринг(ове), който после да присвоиш на SQL пропъртито на query-то.
Re: SQL заявка
Така конструирана заявката ще има проблем с равното на God2 - ако подам '75' няма да върне тези '75хххххххх'...
Re: SQL заявка
И ще е съвсем коректно това, дето ще ти го върне.
Ако все пак пичът е решил, че иска да вземе и тези ЕГН-та, които са по-големи от подаденото, но започват с него (т.е. да ползва за параметър само началните цифри на ЕГН-то), има доста решения - в някои версии на SQL има STARTING [WITH]. А може и да си поиграе човек със стойността на God2 - да не подава само началните цифри, а например 759999999999 - това ще помогне.
Ако все пак пичът е решил, че иска да вземе и тези ЕГН-та, които са по-големи от подаденото, но започват с него (т.е. да ползва за параметър само началните цифри на ЕГН-то), има доста решения - в някои версии на SQL има STARTING [WITH]. А може и да си поиграе човек със стойността на God2 - да не подава само началните цифри, а например 759999999999 - това ще помогне.
Re: SQL заявка
Абе и аз го бях сделал така ,но ....
май забравяме проблем 2000 ЕГН 00ххххх
01ххххх
май забравяме проблем 2000 ЕГН 00ххххх
01ххххх
Re: SQL заявка
А как се отразяваше разликата между 1901 и 2001 примерно в ЕГН-тата?
Принципно щом има разлика между две стойности, значи има и начин да се напасне заявката, така че да върща едната, а да не връща другата - SQL-ът е гъвкаво нещо.
Принципно щом има разлика между две стойности, значи има и начин да се напасне заявката, така че да върща едната, а да не връща другата - SQL-ът е гъвкаво нещо.
Re: SQL заявка
Ами и аз това мъдрувам, макър че стогодишни няма в тази база и
трябва да му подам да примерно всички 1 годишни или от 4 до 10 годишни и именно там заявката се дъни.
трябва да му подам да примерно всички 1 годишни или от 4 до 10 годишни и именно там заявката се дъни.
Re: SQL заявка
Значи намерих нещо:
За родените между 1800 и 1899 се добавя 2 към първата цифра на месеца (т. е. към третата позиция от ЕГН-то).
За родените между 2000 и 2099 се добавя 4 към месеца.
Тъй че ако искаш да върнеш всички между 1 и 4 годишна възраст, God1 ще има стойност 014 (това ще рече всички, родени след 01.01.2001), а God2 - 0449999999. Ако искаш да детайлизираш по месеци, ще трябва да си "конструираш" и ЕГН-то на части - не е сложно и това.
За родените между 1800 и 1899 се добавя 2 към първата цифра на месеца (т. е. към третата позиция от ЕГН-то).
За родените между 2000 и 2099 се добавя 4 към месеца.
Тъй че ако искаш да върнеш всички между 1 и 4 годишна възраст, God1 ще има стойност 014 (това ще рече всички, родени след 01.01.2001), а God2 - 0449999999. Ако искаш да детайлизираш по месеци, ще трябва да си "конструираш" и ЕГН-то на части - не е сложно и това.
Re: SQL заявка
Да беше казал какъв ти е съвъра
Пък и нямаше да е излишно малко по-подробно да ни/си изясниш проблема
Сега гледам в кристалната топка и предполагам:
Сървър : Firebird или подобен (щом пишеш тук, а не в Бази данни)
Имаш таблица с поле "ЕГН" от тип [var]char(10) (Пожелавам ти в действителност това да не е името на полето, аз ще използвам egn)
Искаш бързо и лесно да вадиш списъка на тези които към днешна (или някоя друга дата имат навършени между God1 и God2 години.
Конструкцията на ЕГН-то е доста гадна за да може директно да се извършва бързо (индексирано) търсене на интервали от дати на раждане.
Затова аз предпочитам да сложа едно допълнително поле BirthDay от тип DATE(индексирано), което да се попълва от един BUI тригер. Напр.:
И сега заявките стават много прости и бързи
За твоя случай за да намерим родените между FromDt и ToDt:
Пък и нямаше да е излишно малко по-подробно да ни/си изясниш проблема
Сега гледам в кристалната топка и предполагам:
Сървър : Firebird или подобен (щом пишеш тук, а не в Бази данни)
Имаш таблица с поле "ЕГН" от тип [var]char(10) (Пожелавам ти в действителност това да не е името на полето, аз ще използвам egn)
Искаш бързо и лесно да вадиш списъка на тези които към днешна (или някоя друга дата имат навършени между God1 и God2 години.
Конструкцията на ЕГН-то е доста гадна за да може директно да се извършва бързо (индексирано) търсене на интервали от дати на раждане.
Затова аз предпочитам да сложа едно допълнително поле BirthDay от тип DATE(индексирано), което да се попълва от един BUI тригер. Напр.:
CREATE TRIGGER TESTEGN_BIU0 FOR TESTEGN
ACTIVE BEFORE INSERT OR UPDATE POSITION 0
AS
begin
If(substring(new.egn from 3 for 1) = '2')
then new.birthday=substring(new.egn from 5 for 2)||
'.0'||substring(new.egn from 4 for 1)||
'.18'||substring(new.egn from 1 for 2);
else If(substring(new.egn from 3 for 1) = '3')
then new.birthday=substring(new.egn from 5 for 2)||
'.1'||substring(new.egn from 4 for 1)||
'.18'||substring(new.egn from 1 for 2);
else If(substring(new.egn from 3 for 1) = '4')
then new.birthday=substring(new.egn from 5 for 2)||
'.0'||substring(new.egn from 4 for 1)||
'.20'||substring(new.egn from 1 for 2);
else If(substring(new.egn from 3 for 1) = '5')
then new.birthday=substring(new.egn from 5 for 2)||
'.1'||substring(new.egn from 4 for 1)||
'.20'||substring(new.egn from 1 for 2);
else
new.birthday=substring(new.egn from 5 for 2)||
'.'||substring(new.egn from 3 for 2)||
'.19'||substring(new.egn from 1 for 2);
end
И сега заявките стават много прости и бързи
За твоя случай за да намерим родените между FromDt и ToDt:
select * from testegn
where BirthDay between :FromDt and :ToDt
Редактирано от NDeu на
Re: SQL заявка
Сървъра е MySQL /3.23 за беда/ и тази заявка май няма да свърши работа.
Re: SQL заявка
Май трябва да го разпиша в детайли, за да изясня какво имам предвид.
var YearOfBirth1, YearOfBirth2, Month1, Month2, Day1, Day2: string;
EGN1, EGN2: integer;
.
.
.
.
.
EGN1 := StrToInt(Copy(YearOfBirth1, 3,2) + Month1 + Day1 + '0000');
EGN2 := StrToInt(Copy(YearOfBirth2, 3,2) + Month2 + Day2 + '9999');
if (StrToInt(YearOfBirth2) >= 2000) then EGN2 := EGN2 + 40000000;
.
.
.
.
With Query1 do begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM [таблицата ти] WHERE');
SQL.Add('(EGN >= :EgnFrom) AND (EGN <= :EgnTo)');
Params[0].AsInteger := EGN1;
Params[1].AsInteger := EGN2;
Open;
end;
Не съм го пробвал дали бачка, но е независимо от това коя СУБД ползваш, така че и с MySQL 3.23 не виждам защо да не стане.
Трябват ти само година с 4 цифри, месец с 2 (водещата нула да не забравиш) и дата също с 2 цифри в стрингови променливи (примерно от едит-боксове да си ги вземеш или по друг начин) и ще стане.
var YearOfBirth1, YearOfBirth2, Month1, Month2, Day1, Day2: string;
EGN1, EGN2: integer;
.
.
.
.
.
EGN1 := StrToInt(Copy(YearOfBirth1, 3,2) + Month1 + Day1 + '0000');
EGN2 := StrToInt(Copy(YearOfBirth2, 3,2) + Month2 + Day2 + '9999');
if (StrToInt(YearOfBirth2) >= 2000) then EGN2 := EGN2 + 40000000;
.
.
.
.
With Query1 do begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM [таблицата ти] WHERE');
SQL.Add('(EGN >= :EgnFrom) AND (EGN <= :EgnTo)');
Params[0].AsInteger := EGN1;
Params[1].AsInteger := EGN2;
Open;
end;
Не съм го пробвал дали бачка, но е независимо от това коя СУБД ползваш, така че и с MySQL 3.23 не виждам защо да не стане.
Редактирано от Boby_ на
Re: SQL заявка
if (StrToInt(YearOfBirth2) >= 2000) then EGN2 := EGN2 + 40000000
10х
Ето тва ми убягваше. Благодаря Body.Имам само още един по-труден проблем , със една друга заявка, но нали все пак е клеб Делфи и незнам дали трябва да го задам тук????
10х
Re: SQL заявка
Тогава можеш да имитираш работата на тригера на клиента. При инсертване/ъпдейтване да попълваш и date полето.
Не се притеснявай от това, че се получава някаква денормализация с това допълнително поле
Не се притеснявай от това, че се получава някаква денормализация с това допълнително поле
Re: SQL заявка
Това няма да работи точно по този начин, когато датите ти са в два различни века
Може, разбира се да се поправи, но губиш възможността за индексирано търсене.
И действително Бази данни е по-подходящия клуб за тези въпроси
Може, разбира се да се поправи, но губиш възможността за индексирано търсене.
И действително Бази данни е по-подходящия клуб за тези въпроси
Re: SQL заявка
Ами не виждам защо не - в крайна сметка много често се случва такива проблеми да могат много лесно да се решат в програмния код, а не само в SQL-заявката.
Re: SQL заявка
Прав си, да. Няма да работи добре в тоя случай. Ще се наложи допълнително поле за годината на раждане поне.
Re: SQL заявка
Всъщност има и още един подход: да се раздели ЕГН-то на две части - годината и всичко останало. Така тези 400000, прибавени към втората част, ще осигурят разликата между двата века независимо от това, че годината е само с две цифри.
Само дето после заявката ще е по-сложна, отколкото при твоя вариант с рожденната дата.
