Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите сделать функцию / 6 сообщений из 6, страница 1 из 1
04.05.2007, 12:59
    #34504764
aleksandy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать функцию
Проблема следующая: нужна функция, которая бы формировала и возвращала строку(адрес), на основе переданной в нее строки(кода).
Помогите сделать, так как я полный ламер в этих вопросах.

Поясню подробнее. В функцию передается код адреса(КЛАДРовский) 15 символов.
2 - область (region)
3 - район (zone)
3 - город (city)
3 - населенный пункт (settlement)
4 - улица (street)

Выборка делается из двух таблиц: kladr, streets.
kladr(name, socr, code)
streets(name, socr, code)

Алгоритм такой:
1. В таблице kladr ищется строка вида region + "00000000000" в столбце code и в возвращаемую строку добавляется значение столбца name.
2. Если zone != "000", в таблице kladr ищется строка вида region + zone + "00000000" в столбце code и в возвращаемую строку добавляется значение столбца name.
3. Если city != "000", в таблице kladr ищется строка вида region + zone + city + "00000" в столбце code и в возвращаемую строку добавляется значение столбца name.
4. Если settlement != "000", в таблице kladr ищется строка вида region + zone + city + settlement + "00" в столбце code и в возвращаемую строку добавляется значение столбца name.
5. В таблице streets ищется строка вида region + zone + city + settlement + street + "00" в столбце code и в возвращаемую строку добавляется значение столбца name.
...
Рейтинг: 0 / 0
04.05.2007, 15:01
    #34505265
Kruchinin Pahan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать функцию
aleksandyПроблема следующая: нужна функция, которая бы формировала и возвращала строку(адрес), на основе переданной в нее строки(кода).

Kladr + Street + Doma сейчас больше миллиона записей. Поэтому для своих нужд я разбил код кладра на составляющие Code_FF, Code_RRR, Code_CCC, Code_TTT, Code_SSSS, Code_DDDD ::Int2. Построил индексы и выборки теперь летают приемлемо. Одна из функций как раз заточена на возврат адреса по его коду:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
CREATE OR REPLACE FUNCTION "public"."adr_showname" (varchar, varchar, varchar, varchar, varchar, smallint) RETURNS varchar AS
$body$
/*
Procedure.......: Adr_ShowName()
Author..........: Kruchinin P.N. 2006-11-23
About...........: Функция возвращает собирательное название адреса и его характеристики по
                  заданному коду адресного классификатора, а так же номеру дома, корпусу и квартире.
Parameters......: tcCode         - Код адресного классификатора. Может быть 13, 17, 19 символов для
                                   адресов, улиц и домов соответственно.
                  tcMask         - Маска возврата. Разделитель '|' говорит, что блок между такими
                                 разделителями является самостоятельным блоком, и если в нем остались
                                 незамененные выражения, этот блок возвращен не будет. То, что указывается
                                 в '%', считается предикатом и ему подыскивается подходящая замена.
                                 Учтите, функция Replace регистрозависимая. Если сомневаетесь, как написать,
                                 обратитесь к массиву laSubst. Пример использования приведен в переменной lcMask
                  tcHouse        - Номер дома строкой.
                  tcKorp         - Номер корпуса строкой.
                  tcKvart        - Номер квартиры строкой.
                  tlParseHouse   - Флаг включения/отключения поиска соответствия в Adr_Doma
                                 0 - Поиск не производится. Рекомендуется выставлять, если вам неизвестен дом,
                                 или в строке возврата нет вывода индекса, кода гни, окатд и т.п.
                                 1 - Поиск производится по коду адресного классификатора. Рекомендуется в том
                                 случае, если вам известен 19 значный код адресного классификатора (включающий код дома).
                                 2 - Поиск производится методом парсинга строк Adr_Doma.Name на предмет совпадения
                                 с номером дома, указанным в параметрах tcHouse, tcKorp. Может значительно замедлить
                                 работу. При этом, возможна неоднозначность получения данных.
*/
DECLARE
       tcCode       ALIAS FOR $ 1  ;
       tcMask       ALIAS FOR $ 2  ;
       tcHouse      ALIAS FOR $ 3  ;
       tcKorp       ALIAS FOR $ 4  ;
       tcKvart      ALIAS FOR $ 5  ;
       tlParseHouse ALIAS FOR $ 6  ;

       lcResult       VARCHAR = '' ;
       lcMask         VARCHAR =
       '%Index%. |%FF_Name% %FF_Socr%|, %RRR_Name% %RRR_Socr%|, %CCC_Name% %CCC_Socr%|' ||
       ', %TTT_Name% %TTT_Socr%|, %SSSS_Name% %SSSS_Socr%|' ||
       ', д. %DDDD_1%| кор. %DDDD_2%| кв. %DDDD_3%' ;
       lcHouse        VARCHAR = '' ;
       lcKorp         VARCHAR = '' ;

       laSubst        VARCHAR[][] = ARRAY[
                      ['FF_Kod', ''],     -- 1
                      ['FF_Name', ''],    -- 2
                      ['FF_Socr', ''],    -- 3
                      ['FF_Code', ''],    -- 4
                      ['RRR_Kod', ''],    -- 5
                      ['RRR_Name', ''],   -- 6
                      ['RRR_Socr', ''],   -- 7
                      ['RRR_Code', ''],   -- 8
                      ['CCC_Kod', ''],    -- 9
                      ['CCC_Name', ''],   -- 10
                      ['CCC_Socr', ''],   -- 11
                      ['CCC_Code', ''],   -- 12
                      ['TTT_Kod', ''],    -- 13
                      ['TTT_Name', ''],   -- 14
                      ['TTT_Socr', ''],   -- 15
                      ['TTT_Code', ''],   -- 16
                      ['SSSS_Kod', ''],   -- 17
                      ['SSSS_Name', ''],  -- 18
                      ['SSSS_Socr', ''],  -- 19
                      ['SSSS_Code', ''],  -- 20
                      ['DDDD_Kod', ''],   -- 21
                      ['DDDD_Name', ''],  -- 22
                      ['DDDD_Socr', ''],  -- 23
                      ['DDDD_Code', ''],  -- 24
                      ['DDDD_1', ''],     -- 25
                      ['DDDD_2', ''],     -- 26
                      ['DDDD_3', ''],     -- 27
                      ['Index', ''],      -- 28
                      ['GniNmb', ''],     -- 29
                      ['Uno', ''],        -- 30
                      ['Ocatd', '']       -- 31
                      ] ;


       Code_FF        Int2 =  0  ;
       Code_RRR       Int2 =  0  ;
       Code_CCC       Int2 =  0  ;
       Code_TTT       Int2 =  0  ;
       Code_SSSS      Int2 =  0  ;
       Code_DDDD      Int2 =  0  ;
       IsActual       Int2 =  0  ;
       Row_Kladr      Public.Adr_Kladr ;
       Row_Street     Public.Adr_Street ;
       Row_Doma       Public.Adr_Doma ;

       RetData        CURSOR
                           (tnFF Int2, tnRRR Int2, tnCCC Int2, tnTTT Int2, tnAct Int2)
                           IS SELECT * FROM Adr_Kladr WHERE
                           Adr_Kladr.Code_FF = tnFF
                           AND Adr_Kladr.Code_RRR = tnRRR
                           AND Adr_Kladr.Code_CCC = tnCCC
                           AND Adr_Kladr.Code_TTT = tnTTT
                           AND Adr_Kladr.IsActual = tnAct
                           LIMIT  1  ;
       RetDataStr     CURSOR
                           (tnFF Int2, tnRRR Int2, tnCCC Int2, tnTTT Int2, tnSSSS Int2, tnAct Int2)
                           IS SELECT * FROM Adr_Street WHERE
                           Adr_Street.Code_FF = tnFF
                           AND Adr_Street.Code_RRR = tnRRR
                           AND Adr_Street.Code_CCC = tnCCC
                           AND Adr_Street.Code_TTT = tnTTT
                           AND Adr_Street.Code_SSSS = tnSSSS
                           AND Adr_Street.IsActual = tnAct
                           LIMIT  1  ;
       RetDataDom     CURSOR
                           (tnFF Int2, tnRRR Int2, tnCCC Int2, tnTTT Int2, tnSSSS Int2, tnDDDD Int2)
                           IS SELECT * FROM Adr_Doma WHERE
                           Adr_Doma.Code_FF = tnFF
                           AND Adr_Doma.Code_RRR = tnRRR
                           AND Adr_Doma.Code_CCC = tnCCC
                           AND Adr_Doma.Code_TTT = tnTTT
                           AND Adr_Doma.Code_SSSS = tnSSSS
                           AND Adr_Doma.Code_DDDD = tnDDDD
                           LIMIT  1  ;

       lnCnt_P        INTEGER ;
       lnCnt_S        INTEGER ;
       laPredicats    VARCHAR [] ;
       lcPredicat     VARCHAR ;

BEGIN
   IF (tcCode IS NULL) OR Length(tcCode)< 2  THEN
      RETURN NULL ;
   END IF ;
   IF NOT ((tcMask IS NULL) OR Length(tcMask)= 0 ) THEN
      lcMask = tcMask ;
   END IF ;
   IF NOT ((tcHouse IS NULL) OR Length(tcHouse)= 0 ) THEN
      laSubst[ 25 ][ 2 ] := Trim(tcHouse) ;
      lcHouse        := Trim(tcHouse) ;
   END IF ;
   IF NOT ((tcKorp IS NULL) OR Length(tcKorp)= 0 ) THEN
      laSubst[ 26 ][ 2 ] := Trim(tcKorp) ;
      lcKorp         := Trim(tcKorp) ;
   END IF ;
   IF NOT ((tcKvart IS NULL) OR Length(tcKvart)= 0 ) THEN
      laSubst[ 27 ][ 2 ] := Trim(tcKvart) ;
   END IF ;

   /* Парсинг строки кода */
   IF Length(Trim(tcCode)) >=  2  THEN -- Регион
      Code_FF := Substr(tcCode,  1 ,  2 )::Int2 ;
      IF Code_FF <>  0  THEN
         OPEN RetData (Code_FF, Code_RRR, Code_CCC, Code_TTT, IsActual) ;
         FETCH RetData INTO Row_Kladr ;
         CLOSE RetData ;
         laSubst[ 0  +  1 ][ 2 ] := Coalesce(Trim(Row_Kladr.Kod), '') ;
         laSubst[ 0  +  2 ][ 2 ] := Coalesce(Trim(Row_Kladr.Name), '') ;
         laSubst[ 0  +  3 ][ 2 ] := Coalesce(Trim(Row_Kladr.Socr), '') ;
         laSubst[ 0  +  4 ][ 2 ] := Coalesce(Trim(Row_Kladr.Code), '') ;
         IF Length(Coalesce(Trim(Row_Kladr.Index), '')) >  0  THEN
            laSubst[ 28 ][ 2 ] := Trim(Row_Kladr.Index) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.GniNmb), '')) >  0  THEN
            laSubst[ 29 ][ 2 ] := Trim(Row_Kladr.GniNmb) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.Uno), '')) >  0  THEN
            laSubst[ 30 ][ 2 ] := Trim(Row_Kladr.Uno) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.Ocatd), '')) >  0  THEN
            laSubst[ 31 ][ 2 ] := Trim(Row_Kladr.Ocatd) ;
         END IF ;
      END IF ;
   END IF ;
   IF Length(Trim(tcCode)) >=  5  THEN -- Район
      Code_RRR := Substr(tcCode,  3 ,  3 )::Int2 ;
      IF Code_RRR <>  0  THEN
         OPEN RetData (Code_FF, Code_RRR, Code_CCC, Code_TTT, IsActual) ;
         FETCH RetData INTO Row_Kladr ;
         CLOSE RetData ;
         laSubst[ 4  +  1 ][ 2 ] := Coalesce(Trim(Row_Kladr.Kod), '') ;
         laSubst[ 4  +  2 ][ 2 ] := Coalesce(Trim(Row_Kladr.Name), '') ;
         laSubst[ 4  +  3 ][ 2 ] := Coalesce(Trim(Row_Kladr.Socr), '') ;
         laSubst[ 4  +  4 ][ 2 ] := Coalesce(Trim(Row_Kladr.Code), '') ;
         IF Length(Coalesce(Trim(Row_Kladr.Index), '')) >  0  THEN
            laSubst[ 28 ][ 2 ] := Trim(Row_Kladr.Index) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.GniNmb), '')) >  0  THEN
            laSubst[ 29 ][ 2 ] := Trim(Row_Kladr.GniNmb) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.Uno), '')) >  0  THEN
            laSubst[ 30 ][ 2 ] := Trim(Row_Kladr.Uno) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.Ocatd), '')) >  0  THEN
            laSubst[ 31 ][ 2 ] := Trim(Row_Kladr.Ocatd) ;
         END IF ;
      END IF ;
   END IF ;
   IF Length(Trim(tcCode)) >=  8  THEN -- Город
      Code_CCC := Substr(tcCode,  6 ,  3 )::Int2 ;
      IF Code_CCC <>  0  THEN
         OPEN RetData (Code_FF, Code_RRR, Code_CCC, Code_TTT, IsActual) ;
         FETCH RetData INTO Row_Kladr ;
         CLOSE RetData ;
         laSubst[ 8  +  1 ][ 2 ] := Coalesce(Trim(Row_Kladr.Kod), '') ;
         laSubst[ 8  +  2 ][ 2 ] := Coalesce(Trim(Row_Kladr.Name), '') ;
         laSubst[ 8  +  3 ][ 2 ] := Coalesce(Trim(Row_Kladr.Socr), '') ;
         laSubst[ 8  +  4 ][ 2 ] := Coalesce(Trim(Row_Kladr.Code), '') ;
         IF Length(Coalesce(Trim(Row_Kladr.Index), '')) >  0  THEN
            laSubst[ 28 ][ 2 ] := Trim(Row_Kladr.Index) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.GniNmb), '')) >  0  THEN
            laSubst[ 29 ][ 2 ] := Trim(Row_Kladr.GniNmb) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.Uno), '')) >  0  THEN
            laSubst[ 30 ][ 2 ] := Trim(Row_Kladr.Uno) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.Ocatd), '')) >  0  THEN
            laSubst[ 31 ][ 2 ] := Trim(Row_Kladr.Ocatd) ;
         END IF ;
      END IF ;
   END IF ;
   IF Length(Trim(tcCode)) >=  11  THEN -- Населенный пункт.
      Code_TTT := Substr(tcCode,  9 ,  3 )::Int2 ;
      IF Code_TTT <>  0  THEN
         OPEN RetData (Code_FF, Code_RRR, Code_CCC, Code_TTT, IsActual) ;
         FETCH RetData INTO Row_Kladr ;
         CLOSE RetData ;
         laSubst[ 12  +  1 ][ 2 ] := Coalesce(Trim(Row_Kladr.Kod), '') ;
         laSubst[ 12  +  2 ][ 2 ] := Coalesce(Trim(Row_Kladr.Name), '') ;
         laSubst[ 12  +  3 ][ 2 ] := Coalesce(Trim(Row_Kladr.Socr), '') ;
         laSubst[ 12  +  4 ][ 2 ] := Coalesce(Trim(Row_Kladr.Code), '') ;
         IF Length(Coalesce(Trim(Row_Kladr.Index), '')) >  0  THEN
            laSubst[ 28 ][ 2 ] := Trim(Row_Kladr.Index) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.GniNmb), '')) >  0  THEN
            laSubst[ 29 ][ 2 ] := Trim(Row_Kladr.GniNmb) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.Uno), '')) >  0  THEN
            laSubst[ 30 ][ 2 ] := Trim(Row_Kladr.Uno) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Kladr.Ocatd), '')) >  0  THEN
            laSubst[ 31 ][ 2 ] := Trim(Row_Kladr.Ocatd) ;
         END IF ;
      END IF ;
   END IF ;
   IF Length(Trim(tcCode)) >=  15  THEN -- Улица
      Code_SSSS := Substr(tcCode,  12 ,  4 )::Int2 ;
      IF Code_SSSS <>  0  THEN
         OPEN RetDataStr (Code_FF, Code_RRR, Code_CCC, Code_TTT, Code_SSSS, IsActual) ;
         FETCH RetDataStr INTO Row_Street ;
         CLOSE RetDataStr ;
         laSubst[ 16  +  1 ][ 2 ] := Coalesce(Trim(Row_Street.Kod), '') ;
         laSubst[ 16  +  2 ][ 2 ] := Coalesce(Trim(Row_Street.Name), '') ;
         laSubst[ 16  +  3 ][ 2 ] := Coalesce(Trim(Row_Street.Socr), '') ;
         laSubst[ 16  +  4 ][ 2 ] := Coalesce(Trim(Row_Street.Code), '') ;
         IF Length(Coalesce(Trim(Row_Street.Index), '')) >  0  THEN
            laSubst[ 28 ][ 2 ] := Trim(Row_Street.Index) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Street.GniNmb), '')) >  0  THEN
            laSubst[ 29 ][ 2 ] := Trim(Row_Street.GniNmb) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Street.Uno), '')) >  0  THEN
            laSubst[ 30 ][ 2 ] := Trim(Row_Street.Uno) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Street.Ocatd), '')) >  0  THEN
            laSubst[ 31 ][ 2 ] := Trim(Row_Street.Ocatd) ;
         END IF ;
      END IF ;
   END IF ;
   IF Coalesce(tlParseHouse,  0 )= 1  AND Length(Trim(tcCode)) >=  19  THEN -- Поиск по домам (если указан код).
      Code_DDDD := Substr(tcCode,  16 ,  4 )::Int2 ;
      IF Code_DDDD <>  0  THEN
         OPEN RetDataDom (Code_FF, Code_RRR, Code_CCC, Code_TTT, Code_SSSS, Code_DDDD) ;
         FETCH RetDataDom INTO Row_Doma ;
         CLOSE RetDataDom ;
         laSubst[ 20  +  1 ][ 2 ] := Coalesce(Trim(Row_Doma.Kod), '') ;
         laSubst[ 20  +  2 ][ 2 ] := Coalesce(Trim(Row_Doma.Name), '') ;
         laSubst[ 20  +  3 ][ 2 ] := Coalesce(Trim(Row_Doma.Socr), '') ;
         laSubst[ 20  +  4 ][ 2 ] := Coalesce(Trim(Row_Doma.Code), '') ;
         IF Length(Coalesce(Trim(Row_Doma.Index), '')) >  0  THEN
            laSubst[ 28 ][ 2 ] := Trim(Row_Doma.Index) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Doma.GniNmb), '')) >  0  THEN
            laSubst[ 29 ][ 2 ] := Trim(Row_Doma.GniNmb) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Doma.Uno), '')) >  0  THEN
            laSubst[ 30 ][ 2 ] := Trim(Row_Doma.Uno) ;
         END IF ;
         IF Length(Coalesce(Trim(Row_Doma.Ocatd), '')) >  0  THEN
            laSubst[ 31 ][ 2 ] := Trim(Row_Doma.Ocatd) ;
         END IF ;
      END IF ;
   ELSIF Coalesce(tlParseHouse,  0 )= 2  AND Length(Trim(lcHouse)) >=  0  THEN -- Поиск по домам (если указан дом).
      Code_DDDD :=  0  ;
      FOR Row_Doma IN SELECT *
                        FROM Adr_Doma
                        WHERE
                           Adr_Doma.Code_FF = Code_FF
                           AND Adr_Doma.Code_RRR = Code_RRR
                           AND Adr_Doma.Code_CCC = Code_CCC
                           AND Adr_Doma.Code_TTT = Code_TTT
                           AND Adr_Doma.Code_SSSS = Code_SSSS
                        LOOP
          IF Adr_ParseDom(Row_Doma.Name, lcHouse, lcKorp) THEN
             laSubst[ 20  +  1 ][ 2 ] := Coalesce(Trim(Row_Doma.Kod), '') ;
             laSubst[ 20  +  2 ][ 2 ] := Coalesce(Trim(Row_Doma.Name), '') ;
             laSubst[ 20  +  3 ][ 2 ] := Coalesce(Trim(Row_Doma.Socr), '') ;
             laSubst[ 20  +  4 ][ 2 ] := Coalesce(Trim(Row_Doma.Code), '') ;
             IF Length(Coalesce(Trim(Row_Doma.Index), '')) >  0  THEN
                laSubst[ 28 ][ 2 ] := Trim(Row_Doma.Index) ;
             END IF ;
             IF Length(Coalesce(Trim(Row_Doma.GniNmb), '')) >  0  THEN
                laSubst[ 29 ][ 2 ] := Trim(Row_Doma.GniNmb) ;
             END IF ;
             IF Length(Coalesce(Trim(Row_Doma.Uno), '')) >  0  THEN
                laSubst[ 30 ][ 2 ] := Trim(Row_Doma.Uno) ;
             END IF ;
             IF Length(Coalesce(Trim(Row_Doma.Ocatd), '')) >  0  THEN
                laSubst[ 31 ][ 2 ] := Trim(Row_Doma.Ocatd) ;
             END IF ;
          END IF ;
      END LOOP ;
   END IF ;

   laPredicats := String_To_Array(lcMask, '|') ;
   FOR lnCnt_P IN Array_Lower(laPredicats,  1 )..Array_Upper(laPredicats,  1 ) LOOP -- Цикл по предикатам для замены.
       lcPredicat := laPredicats[lnCnt_P] ;
       FOR lnCnt_S IN Array_Lower(laSubst,  1 )..Array_Upper(laSubst,  1 ) LOOP -- Цикл по возможным значениям замены.
           IF Length(laSubst[lnCnt_S][ 2 ])>  0  THEN
              lcPredicat := Replace(lcPredicat, '%' || laSubst[lnCnt_S][ 1 ] || '%', laSubst[lnCnt_S][ 2 ]) ;
           END IF ;
       END LOOP ;
       IF StrPos(lcPredicat, '%')= 0  THEN -- Если что-то не заменилось, то мы этот предикат не покажем.
          lcResult := lcResult || lcPredicat ;
       END IF ;
   END LOOP ;


   RETURN lcResult ;
END ;
$body$
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;
...
Рейтинг: 0 / 0
04.05.2007, 20:30
    #34506236
aleksandy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать функцию
Kruchinin Pahan я разбил код кладра на составляющие Code_FF, Code_RRR, Code_CCC, Code_TTT, Code_SSSS, Code_DDDD ::Int2. Построил индексы и выборки теперь летают приемлемо.

Спасибо за помощь.
Ещё несколько вопросов:
1. Code_FF, Code_RRR, Code_CCC, Code_TTT, Code_SSSS
это как я понимаю коды областей, районов, городов, населенный пунктов, улиц соответственно, а что такое Code_DDDD, коды номеров домов? Для чего их хранить в отдельной таблице? Эти значения я храню в полях своих таблиц.

2. Немного не в тему, но все же... при создании индекса нужно указывать Access method(rtree, btree, hash, gist), что это за параметр? Как его значение влияет на работу с индексом? И в чем между ними(значениями) разница?
...
Рейтинг: 0 / 0
04.05.2007, 20:35
    #34506243
aleksandy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать функцию
Kruchinin Pahan , может посоветуете какую-нибудь книжку типа plpgsql для начинающих?
...
Рейтинг: 0 / 0
07.05.2007, 06:30
    #34508338
Kruchinin Pahan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать функцию
aleksandy
Спасибо за помощь.
Ещё несколько вопросов:
1. Code_FF, Code_RRR, Code_CCC, Code_TTT, Code_SSSS
это как я понимаю коды областей, районов, городов, населенный пунктов, улиц соответственно, а что такое Code_DDDD, коды номеров домов? Для чего их хранить в отдельной таблице? Эти значения я храню в полях своих таблиц.

Это наследство последней версии КЛАДРа. Разработчики разделили уже на 4 таблицы.
Kladr,
Street,
Doma,
Flats
Заполненную Flats я ни разу не видел (тока заголовок). Doma пока что тоже несильно заполнены, но уже есть. Фишка в этих домах в том, что одна и та же улица может иметь несколько почтовых индексов и номеров ГНИ. Опять же проблема с тем, как этот дом хранится. Пока я с ним особенно ничего не придумал. Есть только функция Adr_ParseDom. Тока она тормоз.

aleksandy
2. Немного не в тему, но все же... при создании индекса нужно указывать Access method(rtree, btree, hash, gist), что это за параметр? Как его значение влияет на работу с индексом? И в чем между ними(значениями) разница?
Это тип ндекса. Для Int2, Int4 я предпочитаю btree. Время поиска в таком индексе стремится к O(lg(h)), где h - высота индекса дерева. lg(h) - столько в максимуме операций чтения с диска необходимо, чтобы получить конкретный ключ. Сейчас народ предпочитает пользоваться Gist индексами (на самом деле то же красночерное дерево, только слегка модифицированное для поддержания сбалансированности дерева).
Хаш, вроде лучше для текстов использовать (только на хаш индексах не определены часть операций сравнения, как на btree).
А вообще, в доках по пг есть все и про индексы, и какие операции определены на этих индексах и где какой лучше использовать.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
CREATE OR REPLACE FUNCTION "public"."adr_parsedom" (varchar, varchar, varchar) RETURNS boolean AS
$body$
/*
Procedure.......: Adr_ParseDom()
Author..........: Kruchinin P.N. 2006-11-23
About...........: Функция проверяет, входит ли этот дом (корпус) в границы, зашифрованные в строке Adr_Doma.Name
Parameters......: tcMask  - Строка в стиле Adr_Doma.Name
                  tcHouse - Строка с номером дома
                  tcKorp  - Строка с корпусом дома.
*/
DECLARE
       tcMask   ALIAS FOR $ 1  ;
       tcHouse  ALIAS FOR $ 2  ;
       tcKorp   ALIAS FOR $ 3  ;

       lcHouse  VARCHAR = '' ;
       lcKorp   VARCHAR = '' ;
       laPred   VARCHAR[] ;
       laRng    INTEGER[] ;
       lnCnt    INTEGER ;
       lcPred   VARCHAR ;
       llNoKorp BOOLEAN = False ;
BEGIN
   IF Length(Coalesce(Trim(tcMask), ''))= 0  THEN
      RETURN False ;
   END IF ;
   lcHouse := Coalesce(Trim(tcHouse), '') ;
   lcKorp := Coalesce(Trim(tcKorp), '') ;
   IF Length(lcHouse)= 0  THEN
      RETURN False ;
   END IF ;
   llNoKorp := (Length(lcKorp)= 0 ) ;

   laPred := String_To_Array(tcMask, ',') ;
   FOR lnCnt IN Array_Lower(laPred,  1 )..Array_Upper(laPred,  1 ) LOOP
       lcPred := Trim(laPred[lnCnt]);
       IF NOT llNoKorp AND StrPos(lcPred, '/') >  0  THEN -- Дом с корпусом (однозначное соответствие).
          IF (lcHouse || '/' || lcKorp) = lcPred THEN
             RETURN True ;
          END IF ;
       ELSIF NOT llNoKorp AND Replace(lcPred, ' ', '')=(lcHouse || '' || lcKorp) THEN -- Проверка дома с корпусом.
          RETURN True ;
       ELSIF llNoKorp AND lcPred = lcHouse THEN -- Вот он сразу и дом.
          RETURN True ;
       ELSIF llNoKorp AND StrPos(lcPred, '-') >  0  AND Left(lcPred,  1 ) = 'Ч' THEN -- Границы четных номеров.
          IF lcHouse::Int4 %  2  =  0  THEN
             -- Вычистим предикат.
             lcPred := Replace(lcPred, 'Ч', '') ;
             lcPred := Replace(lcPred, '(', '') ;
             lcPred := Replace(lcPred, ')', '') ;
             -- Найдем границы.
             laRng := String_To_Array(lcPred, '-') ;
             IF Numeric_Smaller(lcHouse::Int4,  998 ) BETWEEN laRng[Array_Lower(laRng,  1 )] AND laRng[Array_Upper(laRng,  1 )] THEN
                RETURN True ;
             END IF ;
          END IF ;
       ELSIF llNoKorp AND StrPos(lcPred, '-') >  0  AND Left(lcPred,  1 ) = 'Н' THEN -- Границы нечетных номеров.
          IF lcHouse::Int4 %  2  =  1  THEN
             -- Вычистим предикат.
             lcPred := Replace(lcPred, 'Н', '') ;
             lcPred := Replace(lcPred, '(', '') ;
             lcPred := Replace(lcPred, ')', '') ;
             -- Найдем границы.
             laRng := String_To_Array(lcPred, '-') ;
             IF Numeric_Smaller(lcHouse::Int4,  999 ) BETWEEN laRng[Array_Lower(laRng,  1 )] AND laRng[Array_Upper(laRng,  1 )] THEN
                RETURN True ;
             END IF ;
          END IF ;
       ELSIF llNoKorp AND StrPos(lcPred, '-') >  0  THEN -- Границы любых номеров.
          -- Вычистим предикат.
          lcPred := Replace(lcPred, '(', '') ;
          lcPred := Replace(lcPred, ')', '') ;
          -- Найдем границы.
          laRng := String_To_Array(lcPred, '-') ;
          IF lcHouse::Int4 BETWEEN laRng[Array_Lower(laRng,  1 )] AND laRng[Array_Upper(laRng,  1 )] THEN
             RETURN True ;
          END IF ;
       END IF ;
   END LOOP ;

   RETURN False ;
END ;
$body$
LANGUAGE 'plpgsql' STABLE CALLED ON NULL INPUT SECURITY INVOKER;
...
Рейтинг: 0 / 0
07.05.2007, 06:31
    #34508339
Kruchinin Pahan
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите сделать функцию
aleksandy Kruchinin Pahan , может посоветуете какую-нибудь книжку типа plpgsql для начинающих?
Не посоветую. ;-/ Сам обычно хелп читаю и форум.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите сделать функцию / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]