Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: VBA & SQL
 
 автор: kirillxx   (26.08.2009 в 23:25)   письмо автору
 
 

Привет всем.
Возникла задача привести текст, а именно адреса из таблицы к определенному виду, что бы сравнивать их с другой таблицей. Как я понимаю, необходимо написать функцию или процедуру. Алгоритм понятен, я даже сделал это на 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 ;

  Ответить  
 
 автор: heed   (27.08.2009 в 01:52)   письмо автору
 
   для: 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 

  Ответить  
 
 автор: Trianon   (27.08.2009 в 11:27)   письмо автору
 
   для: kirillxx   (26.08.2009 в 23:25)
 

неплохо было бы выразить этот алгоритм структурным образом (то есть без go to).

  Ответить  
 
 автор: kirillxx   (27.08.2009 в 23:05)   письмо автору
 
   для: Trianon   (27.08.2009 в 11:27)
 

вот эта вот фраза к кому была обращена? )))))
я даже и не понял, о чем это
Что значит структурным языком?

  Ответить  
 
 автор: Trianon   (27.08.2009 в 23:16)   письмо автору
 
   для: kirillxx   (27.08.2009 в 23:05)
 

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

  Ответить  
 
 автор: kirillxx   (27.08.2009 в 23:10)   письмо автору
 
   для: Trianon   (27.08.2009 в 11:27)
 

А как в SQL обазначить пробел. Это то же самое что NULL? или есть отличия???

  Ответить  
 
 автор: Trianon   (27.08.2009 в 23:16)   письмо автору
 
   для: kirillxx   (27.08.2009 в 23:10)
 

как любой другой символ. ' '
NULL это не только не пробел и не символ, но даже не значение.

  Ответить  
 
 автор: kirillxx   (27.08.2009 в 23:48)   письмо автору
 
   для: Trianon   (27.08.2009 в 23:16)
 

Почему то не могу пройти запись
a = Length('aaa');
что здесь не так?

  Ответить  
 
 автор: heed   (28.08.2009 в 01:16)   письмо автору
 
   для: 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)

  Ответить  
 
 автор: heed   (28.08.2009 в 03:17)   письмо автору
 
   для: kirillxx   (27.08.2009 в 23:48)
 

что-то не то сказал.
если в DECLARE объявлена эта a, и aaa это параметр, то всё правильно
SET a = Length(aaa);

  Ответить  
 
 автор: kirillxx   (31.08.2009 в 14:16)   письмо автору
 
   для: 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

Подскажите что ему не нравиться

  Ответить  
 
 автор: Trianon   (31.08.2009 в 15:48)   письмо автору
 
   для: kirillxx   (31.08.2009 в 14:16)
 

http://dev.mysql.com/doc/refman/5.1/en/create-procedure.html

У параметра функции должен быть указан тип.
И диагностика в точности указывает точку именно этой причину.

  Ответить  
 
 автор: kirillxx   (02.09.2009 в 01:01)   письмо автору
 
   для: 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 не подразумевает, что здесь можно писать текст????

  Ответить  
 
 автор: Trianon   (02.09.2009 в 01:42)   письмо автору
 
   для: kirillxx   (02.09.2009 в 01:01)
 

подразумевает.
Да только текст на языке SQL тоже оформляется по правилам синтаксиса.
http://dev.mysql.com/doc/refman/5.0/en/string-syntax.html

  Ответить  
 
 автор: heed   (02.09.2009 в 12:45)   письмо автору
 
   для: 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))

  Ответить  
 
 автор: kirillxx   (02.09.2009 в 23:47)   письмо автору
 
   для: heed   (02.09.2009 в 12:45)
 

Существует две таблицы в которых указаны адреса
В одной тип 123123 77 Россолимо ул.5 к.2 кв.3
В другой тип Россолимо ул. 5 к. 2 кв. 3
Задача состоит в том, что бы найти одинаковые адреса в двух таблицах и сопоставить данные,
Что бы получилась однородная и полная таблица или выборка.
Так как адреса записаны по разному (индекс, регион, пробелы после улицы, копруса и кв.) Сопоставить их не удается. Вот и пытаюсь создать функцию, которая будет брать один адрес и приводить его к виду другому, а уж потом искать. Может это можно как то проще сделать?

  Ответить  
 
 автор: Trianon   (03.09.2009 в 00:19)   письмо автору
 
   для: kirillxx   (02.09.2009 в 23:47)
 

>Вот и пытаюсь создать функцию, которая будет брать один адрес и приводить его к виду другому, а уж потом искать. Может это можно как то проще сделать?


В целом, подход понятен.
Что можно посоветовать?
1. Определиться с нормальной (канонической) формой адреса. Которая бы не содержала несущественных пробелов, разночтений в написании региона, улицы, корпуса, квартиры и т.д, текста в разном регистре и т.п.
2. Создать в таблице поле под такую форму. Если его нет в обеих таблицах - создать в обеих.
3. Запустить процесс заполнения этого поля - и вовсе необязательно, чтоб он обрабатывал всю табллицу за раз. За сколько может - пусть столько и делает. Вероятно, есть смысл не опираться лишь на хранимые процедуры, а привлечь клиентские мощности (php, C++, vba - неважно)
4. Если поле имеет изрядный вес - посчитать хеш этого поля. И использовать хеш в качестве ключа.
Если нет - в качестве ключа использовать само поле.
5. Выполнить сопоставление таблиц по ключу.
как-то так...

  Ответить  
 
 автор: kirillxx   (03.09.2009 в 01:38)   письмо автору
 
   для: Trianon   (03.09.2009 в 00:19)
 

Сложновато это для меня ))) php, C++.
Может можно эту услугу заказать? например у Вас)))) за умеренное вознаграждение

  Ответить  
 
 автор: Trianon   (03.09.2009 в 09:14)   письмо автору
 
   для: kirillxx   (03.09.2009 в 01:38)
 

у меня - всяко не за умеренное.

  Ответить  
 
 автор: kirillxx   (03.09.2009 в 09:18)   письмо автору
 
   для: Trianon   (03.09.2009 в 09:14)
 

У меня поконкретней обсудим?
8-916-513-28-07

  Ответить  
 
 автор: kirillxx   (03.09.2009 в 09:19)   письмо автору
 
   для: kirillxx   (03.09.2009 в 09:18)
 

В смысле, может быть обсудим более конкретно?
8-916-513-28-07

  Ответить  
 
 автор: kirillxx   (03.09.2009 в 13:53)   письмо автору
 
   для: 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

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования