SQL заявка

16 отговора 512 прегледа
#1

SQL заявка

Колеги бихте ли ми помогнали за една SQL заявка
Имам колона ЕГН и две цифри от до /от години God1 до годиниGod2/.
Как да напиша заявката, че да ми извади резултата всички егенета от примерно всички ЕГН - та отговарящи на God1 >= Егн =<God2тази заявка.

Много съм на зор. Помагайте.

Отговор
в отговор на Kolega #2

Re: SQL заявка

Примерно
SELECT * FROM [таблицата ти] WHERE
(EGN >= :God1) AND (EGN <= :God2)

Ако правиш приложение на Делфи, можеш да ползваш параметри на query-то, за да предадеш годините (затова са двете точки пред God1 и God2). Можеш и без параметри, просто като си конструираш стринг(ове), който после да присвоиш на SQL пропъртито на query-то.

Отговор
в отговор на Boby_ #3

Re: SQL заявка

Така конструирана заявката ще има проблем с равното на God2 - ако подам '75' няма да върне тези '75хххххххх'...

Отговор
в отговор на andrew_nikoloff #4

Re: SQL заявка

И ще е съвсем коректно това, дето ще ти го върне.
Ако все пак пичът е решил, че иска да вземе и тези ЕГН-та, които са по-големи от подаденото, но започват с него (т.е. да ползва за параметър само началните цифри на ЕГН-то), има доста решения - в някои версии на SQL има STARTING [WITH]. А може и да си поиграе човек със стойността на God2 - да не подава само началните цифри, а например 759999999999 - това ще помогне.

Отговор
в отговор на Boby_ #5

Re: SQL заявка

Абе и аз го бях сделал така ,но ....
май забравяме проблем 2000 ЕГН 00ххххх
01ххххх

Отговор
в отговор на Kolega #6

Re: SQL заявка

А как се отразяваше разликата между 1901 и 2001 примерно в ЕГН-тата?
Принципно щом има разлика между две стойности, значи има и начин да се напасне заявката, така че да върща едната, а да не връща другата - SQL-ът е гъвкаво нещо.

Отговор
в отговор на Boby_ #7

Re: SQL заявка

Ами и аз това мъдрувам, макър че стогодишни няма в тази база и
трябва да му подам да примерно всички 1 годишни или от 4 до 10 годишни и именно там заявката се дъни.

Отговор
в отговор на Koлera #8

Re: SQL заявка

Значи намерих нещо:
За родените между 1800 и 1899 се добавя 2 към първата цифра на месеца (т. е. към третата позиция от ЕГН-то).
За родените между 2000 и 2099 се добавя 4 към месеца.

Тъй че ако искаш да върнеш всички между 1 и 4 годишна възраст, God1 ще има стойност 014 (това ще рече всички, родени след 01.01.2001), а God2 - 0449999999. Ако искаш да детайлизираш по месеци, ще трябва да си "конструираш" и ЕГН-то на части - не е сложно и това.

Отговор
в отговор на Kolega #9

Re: SQL заявка

Да беше казал какъв ти е съвъра
Пък и нямаше да е излишно малко по-подробно да ни/си изясниш проблема
Сега гледам в кристалната топка и предполагам:
Сървър : 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 на

Отговор
в отговор на NDeu #10

Re: SQL заявка

Сървъра е MySQL /3.23 за беда/ и тази заявка май няма да свърши работа.

Отговор
в отговор на Koлera #11

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 цифри в стрингови променливи (примерно от едит-боксове да си ги вземеш или по друг начин) и ще стане.

Редактирано от Boby_ на

Отговор
в отговор на Boby_ #12

Re: SQL заявка

if (StrToInt(YearOfBirth2) >= 2000) then EGN2 := EGN2 + 40000000
10х Ето тва ми убягваше. Благодаря Body.Имам само още един по-труден проблем , със една друга заявка, но нали все пак е клеб Делфи и незнам дали трябва да го задам тук????

Отговор
в отговор на Koлera #13

Re: SQL заявка

Тогава можеш да имитираш работата на тригера на клиента. При инсертване/ъпдейтване да попълваш и date полето.
Не се притеснявай от това, че се получава някаква денормализация с това допълнително поле

Отговор
в отговор на Koлera #14

Re: SQL заявка

Това няма да работи точно по този начин, когато датите ти са в два различни века
Може, разбира се да се поправи, но губиш възможността за индексирано търсене.
И действително Бази данни е по-подходящия клуб за тези въпроси

Отговор
в отговор на Koлera #15

Re: SQL заявка

Ами не виждам защо не - в крайна сметка много често се случва такива проблеми да могат много лесно да се решат в програмния код, а не само в SQL-заявката.

Отговор
в отговор на NDeu #16

Re: SQL заявка

Прав си, да. Няма да работи добре в тоя случай. Ще се наложи допълнително поле за годината на раждане поне.

Отговор
в отговор на Boby_ #17

Re: SQL заявка

Всъщност има и още един подход: да се раздели ЕГН-то на две части - годината и всичко останало. Така тези 400000, прибавени към втората част, ще осигурят разликата между двата века независимо от това, че годината е само с две цифри. Само дето после заявката ще е по-сложна, отколкото при твоя вариант с рожденната дата.


Отговор