|
|
|
| Привет всем.
Возникла задача привести текст, а именно адреса из таблицы к определенному виду, что бы сравнивать их с другой таблицей. Как я понимаю, необходимо написать функцию или процедуру. Алгоритм понятен, я даже сделал это на VBA, а вот попытка перенести эту функцию в sql пока успехом не увенчалась. Друзья подскажите, что надо изменить в коде, что бы он стал работать в SQL.
DROP FUNCTION IF EXISTS `ndfl`.`q_adres`\\
CREATE FUNCTION `ndfl`.`q_adres` (aaa) RETURNS tinytext
BEGIN
declare NumberУл, NumberД, NumberК, NumberКВ int
a = Len(aaa)
If Mid(aaa, 3, 1) = " " Then
zzz = Mid(aaa, 4, a - 3)
Else
zzz = Mid(aaa, 11, a - 10)
End If
a = Len(zzz)
For i = 1 To a
If Mid(zzz, i, 2) = "ул" Then NumberУЛ = i
If Mid(zzz, i, 2) = "д." Then NumberД = i
If Mid(zzz, i, 2) = "к." Then NumberК = i
If Mid(zzz, i, 3) = "кв." Then NumberКВ = i
Next i
If NumberД <> Empty And NumberК = Empty And NumberКВ = Empty Then GoTo 111
If NumberД <> Empty And NumberК = Empty And NumberКВ <> Empty Then GoTo 222
If NumberД <> Empty And NumberК <> Empty And NumberКВ <> Empty Then GoTo 333
111:
итого = Mid(zzz, 1, NumberУЛ + 1) & "." & " " & Mid(zzz, NumberД, 2) & " " & Mid(zzz, NumberД + 2, a - NumberД + 2)
GoTo bbb
222:
If NumberКВ - NumberД = 5 Then
u = 2
Else
If NumberКВ - NumberД > 5 Then
u = 3
Else
u = 1
End If
End If
итого = Mid(zzz, 1, NumberУЛ + 1) & "." & " " & Mid(zzz, NumberД + 2, u) & " " & Mid(zzz, NumberКВ, 3) & " " & Mid(zzz, NumberКВ + 3, a - NumberКВ + 3)
GoTo bbb
333:
If NumberК - NumberД = 5 Then
u = 2
Else
If NumberК - NumberД > 5 Then
u = 3
Else
u = 1
End If
End If
итого = Mid(zzz, 1, NumberУЛ + 1) & "." & " " & Mid(zzz, NumberД, 2) & " " & Mid(zzz, NumberД + 2, u)
If NumberКВ - NumberК = 4 Then
u = 1
Else
If NumberКВ - NumberК > 4 Then
u = 2
End If
End If
итого = итого & " " & Mid(zzz, NumberК, 2) & " " & Mid(zzz, NumberК + 2, u) & " " & Mid(zzz, NumberКВ, 3) & " " & Mid(zzz, NumberКВ + 3, a - NumberКВ + 3)
GoTo bbb
bbb:
return итого;
END\\
DELIMITER ; | |
|
|
|
|
|
|
|
для: kirillxx
(26.08.2009 в 23:25)
| | итого = Mid(zzz, 1, NumberУЛ + 1) & "." & " " & Mid(zzz, NumberД, 2) & " " & Mid(zzz, NumberД + 2, u)
>>>>
CONCAT()
GoTo насколько знаю. нет
, ещё есть только то что в таких топиках
mysql> HELP Compound Statements
You asked for help about help category: "Compound Statements"
For more information, type 'help <item>', where <item> is one of the following
topics:
BEGIN END
CASE STATEMENT
CLOSE
DECLARE CONDITION
DECLARE CURSOR
DECLARE HANDLER
DECLARE VARIABLE
FETCH
IF STATEMENT
ITERATE
LEAVE
LOOP
OPEN
REPEAT LOOP
RETURN
SELECT INTO
SET VARIABLE
WHILE
|
и в функциях есть
CASE Case statement
IF() If/else construct
IFNULL() Null if/else construct
NULLIF() Return NULL if expr1 = expr2
|
| |
|
|
|
|
|
|
|
для: kirillxx
(26.08.2009 в 23:25)
| | неплохо было бы выразить этот алгоритм структурным образом (то есть без go to). | |
|
|
|
|
|
|
|
для: Trianon
(27.08.2009 в 11:27)
| | вот эта вот фраза к кому была обращена? )))))
я даже и не понял, о чем это
Что значит структурным языком? | |
|
|
|
|
|
|
|
для: kirillxx
(27.08.2009 в 23:05)
| | К Вам, уж коль скоро Вы автор кода.
Структурным образом - значит без применения оператора GO TO .
Конструкциями Составного оператора, условного оператора и оператора цикла. | |
|
|
|
|
|
|
|
для: Trianon
(27.08.2009 в 11:27)
| | А как в SQL обазначить пробел. Это то же самое что NULL? или есть отличия??? | |
|
|
|
|
|
|
|
для: kirillxx
(27.08.2009 в 23:10)
| | как любой другой символ. ' '
NULL это не только не пробел и не символ, но даже не значение. | |
|
|
|
|
|
|
|
для: Trianon
(27.08.2009 в 23:16)
| | Почему то не могу пройти запись
a = Length('aaa');
что здесь не так? | |
|
|
|
|
|
|
|
для: kirillxx
(27.08.2009 в 23:48)
| | В MySQL "=" - оператор сравнения
, или ещё как-то, такая вот беда ;)
mysql> SELECT @x := Length('aaa');
+---------------------+
| @x := Length('aaa') |
+---------------------+
| 3 |
+---------------------+
1 row in set (0.00 sec)
mysql> SELECT @x = Length('aaa');
+--------------------+
| @x = Length('aaa') |
+--------------------+
| 1 |
+--------------------+
1 row in set (0.00 sec)
|
| |
|
|
|
|
|
|
|
для: kirillxx
(27.08.2009 в 23:48)
| | что-то не то сказал.
если в DECLARE объявлена эта a, и aaa это параметр, то всё правильно | |
|
|
|
|
|
|
|
для: heed
(28.08.2009 в 03:17)
| | CREATE FUNCTION `ndfl`.`q_adres` (aaa) RETURNS tinytext
BEGIN
declare NumberУл, NumberД, NumberК, NumberКВ int;
declare a tinytext;
Пишет в ответ
You have an arror in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') RETURNS tinytext
BEGIN
declare NumberУл, NumberД, NumberК, NumberКВ ' at line 1
Подскажите что ему не нравиться | |
|
|
|
|
|
|
|
для: kirillxx
(31.08.2009 в 14:16)
| | http://dev.mysql.com/doc/refman/5.1/en/create-procedure.html
У параметра функции должен быть указан тип.
И диагностика в точности указывает точку именно этой причину. | |
|
|
|
|
|
|
|
для: Trianon
(31.08.2009 в 15:48)
| | Ни хрена не получается
Вот написал функцию. Вроде все прошло. Ответ получить не могу. Более того что либо делает если в качестве аргумента цифры. Если какой либо текст, вообще не работает. Помогите.
CREATE FUNCTION `ndfl`.`q_adres` (aaa TEXT) RETURNS text
BEGIN
declare a, B, i int;
DECLARE zzz text;
set a = length('aaa');
If Mid(aaa, 3, 1) = ' ' Then
SET zzz = Mid(aaa, 4, a - 3);
set B = length('zzz');
Else set zzz = Mid(aaa, 11, a - 10);
set B = length('zzz');
End If;
return zzz;
END
Далее набираю
select q_adres(125654 рпепрорпапрорп);
И ответ снова синтаксическая ошибка. Разве тип данных text не подразумевает, что здесь можно писать текст???? | |
|
|
|
|
|
|
|
для: kirillxx
(02.09.2009 в 01:01)
| | подразумевает.
Да только текст на языке SQL тоже оформляется по правилам синтаксиса.
http://dev.mysql.com/doc/refman/5.0/en/string-syntax.html | |
|
|
|
|
|
|
|
для: kirillxx
(02.09.2009 в 01:01)
| | >set a = length('aaa');
здесь наоборот не должно быть апострофов, если не имеется ввиду строка из трёх букв 'aaa'
и самое главное непонятно какие строки пытаетесь получить из каких строк
, попробовал что-то похожее, понял что 'ул' может быть и проспектом и переулком и проездом и... , и бросил пробовать ;)
DELIMITER $$
CREATE FUNCTION `q_adres` (aaa TINYTEXT) RETURNS TINYTEXT
BEGIN
declare x TINYINT;
DECLARE tmp, ul, d, k, kv, other TINYTEXT;
SET aaa = REPLACE(REPLACE(TRIM(aaa), '.', ' '), ' ', ' ');
SET ul='', d='', k='', kv='', other='';
WHILE LENGTH(aaa) DO
SET tmp = SUBSTRING_INDEX(aaa, ' ', 1),
aaa = INSERT(aaa, 1, 1 + LENGTH(CONVERT(tmp USING cp1251)), '');
CASE
WHEN tmp ='ул' THEN SET x=1;
WHEN tmp ='д' THEN SET x=2;
WHEN tmp ='к' THEN SET x=4;
WHEN tmp ='кв' THEN SET x=8;
ELSE
CASE
WHEN X&1 THEN SET ul = CONCAT_WS(' ', ul, tmp);
WHEN X&2 THEN SET d = CONCAT_WS(' ', d, tmp);
WHEN X&4 THEN SET k = CONCAT_WS(' ', k, tmp);
WHEN X&8 THEN SET kv = CONCAT_WS(' ', kv, tmp);
ELSE SET other = CONCAT_WS(' ', other, tmp);
END CASE;
END CASE;
END WHILE;
SET aaa = CONCAT('населённый_пункт:', other, ';\nулица:', ul, ';\nдом:', d,
';\nкорпус:', k, ';\nквартира:', kv, ';');
return aaa;
END$$
DELIMITER ;
SELECT q_adres('Москва Кремль ул.красная площадь д. 1 кв 1.');
DROP FUNCTION IF EXISTS `q_adres`;
| заметил что LENGTH(tmp) никак не хочет выдавать правильный результат , при моих настройках и использовании MySQLQueryBrowser
, а только
LENGTH(CONVERT(tmp USING cp1251)) | |
|
|
|
|
|
|
|
для: heed
(02.09.2009 в 12:45)
| | Существует две таблицы в которых указаны адреса
В одной тип 123123 77 Россолимо ул.5 к.2 кв.3
В другой тип Россолимо ул. 5 к. 2 кв. 3
Задача состоит в том, что бы найти одинаковые адреса в двух таблицах и сопоставить данные,
Что бы получилась однородная и полная таблица или выборка.
Так как адреса записаны по разному (индекс, регион, пробелы после улицы, копруса и кв.) Сопоставить их не удается. Вот и пытаюсь создать функцию, которая будет брать один адрес и приводить его к виду другому, а уж потом искать. Может это можно как то проще сделать? | |
|
|
|
|
|
|
|
для: kirillxx
(02.09.2009 в 23:47)
| | >Вот и пытаюсь создать функцию, которая будет брать один адрес и приводить его к виду другому, а уж потом искать. Может это можно как то проще сделать?
В целом, подход понятен.
Что можно посоветовать?
1. Определиться с нормальной (канонической) формой адреса. Которая бы не содержала несущественных пробелов, разночтений в написании региона, улицы, корпуса, квартиры и т.д, текста в разном регистре и т.п.
2. Создать в таблице поле под такую форму. Если его нет в обеих таблицах - создать в обеих.
3. Запустить процесс заполнения этого поля - и вовсе необязательно, чтоб он обрабатывал всю табллицу за раз. За сколько может - пусть столько и делает. Вероятно, есть смысл не опираться лишь на хранимые процедуры, а привлечь клиентские мощности (php, C++, vba - неважно)
4. Если поле имеет изрядный вес - посчитать хеш этого поля. И использовать хеш в качестве ключа.
Если нет - в качестве ключа использовать само поле.
5. Выполнить сопоставление таблиц по ключу.
как-то так... | |
|
|
|
|
|
|
|
для: Trianon
(03.09.2009 в 00:19)
| | Сложновато это для меня ))) php, C++.
Может можно эту услугу заказать? например у Вас)))) за умеренное вознаграждение | |
|
|
|
|
|
|
|
для: kirillxx
(03.09.2009 в 01:38)
| | у меня - всяко не за умеренное. | |
|
|
|
|
|
|
|
для: Trianon
(03.09.2009 в 09:14)
| | У меня поконкретней обсудим?
8-916-513-28-07 | |
|
|
|
|
|
|
|
для: kirillxx
(03.09.2009 в 09:18)
| | В смысле, может быть обсудим более конкретно?
8-916-513-28-07 | |
|
|
|
|
|
|
|
для: kirillxx
(03.09.2009 в 09:19)
| | Все переделал и теперь ошибку выдает в самом конце. А в чем она снова не пойму.
CREATE FUNCTION `ndfl`.`q_adres` (aaa TEXT) RETURNS tinytext
BEGIN
declare NumberУл, NumberД, NumberК, NumberКВ, a, B, i, u, X int;
DECLARE zzz, итого text;
SET aaa := REPLACE(REPLACE(TRIM('aaa'), '.', ' '), ' ', ' ');
set a := LENGTH(aaa);
If Mid(aaa, 3, 1) = ' ' Then
SET zzz := Mid(aaa, 4, a - 3);
set B := length('zzz');
Else set zzz := Mid(aaa, 11, a - 10);
set B := length('zzz');
End If;
SET NumberУЛ := position('ул.' in zzz);
SET NumberД := position('д.' in zzz);
SET NumberК = position('к.' in zzz);
SET NumberКВ = position('кв' in zzz);
If NumberД <> 0 And NumberК = 0 And NumberКВ = 0 Then set x := 1;
If NumberД <> 0 And NumberК = 0 And NumberКВ <> 0 Then set x := 2;
If NumberД <> 0 And NumberК <> 0 And NumberКВ <> 0 Then set x := 3;
case
when x&1 then
SET итого := CONCAT(Mid(zzz, 1, NumberУЛ + 1),"." , " ", Mid(zzz, NumberД, 2) ," ", Mid(zzz, NumberД + 2, a - NumberД + 2));
return итого;
WHEN X&2 then
If NumberКВ - NumberД = 5 Then
set u := 2;
Else
If NumberКВ - NumberД > 5 Then
set u := 3;
Else
set u := 1;
End If;
End If;
SET итого := CONCAT(Mid(zzz, 1, NumberУЛ + 1), ".", " ", Mid(zzz, NumberД + 2, u), " ", Mid(zzz, NumberКВ, 3) ," " , Mid(zzz, NumberКВ + 3, a - NumberКВ + 3));
return итого;
when x&3 then
If NumberК - NumberД = 5 Then
set u := 2;
Else
If NumberК - NumberД > 5 Then
set u := 3;
Else
set u := 1;
End If;
End If;
SET итого = CONCAT(Mid(zzz, 1, NumberУЛ + 1),"." , " " , Mid(zzz, NumberД, 2) , " ", Mid(zzz, NumberД + 2, u));
If NumberКВ - NumberК = 4 Then
SET u := 1;
Else
If NumberКВ - NumberК > 4 Then
SET u := 2;
End If;
End If;
SET итого = CONCAT(итого, " ", Mid(zzz, NumberК, 2), " ", Mid(zzz, NumberК + 2, u), " ", Mid(zzz, NumberКВ, 3) , " ", Mid(zzz, NumberКВ + 3, a - NumberКВ + 3));
return итого;
END CASE;
END
Выдает
.... for the right syntax to use near ' ' at line 77
Строка 77 это как раз END | |
|
|
|
|