Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / FoxPro, Visual FoxPro Новый топик    Ответить
 Поможите select написать  [new]
Tigroff
Member

Откуда:
Сообщений: 20
Сидю, мучаюсь:
есть курсор А:
  номер  |   кол   | назв  |
1 | 1 | a |
1 | 4 | b |
1 | 5 | v |
2 | 2 | a |
2 | 1 | d |
2 | 2 | b |
5 | 1 | c |
5 | 1 | l |
....
и табличка В:
  номер | кол_сум |    назв     |
1 | 10 | a, b, v |
2 | 5 | a, d, b |
5 | 2 | c,b |
....
Как заполнить 2 первых поля в таблице В, понятно: select номер, sum(кол) as кол_сум group by номер
А вот как заполнить третье поле, никак не могу придумать. Записей в курсоре порядка 20000.
Мож есть какой-нибудь хитрый select?
 
	    

        
9 апр 08, 16:34    [5525782]     Ответить | Цитировать Сообщить модератору
 Re: Поможите select написать  [new]
12345вышелзайчикпогулять
Guest
https://www.sql.ru/forum/actualthread.aspx?tid=539952
9 апр 08, 17:07    [5526032]     Ответить | Цитировать Сообщить модератору
 Re: Поможите select написать  [new]
Tigroff
Member

Откуда:
Сообщений: 20
to 12345вышелзайчикпогулять

А как-нить попросче? Медленно...
Форма, вкоторой все это нужно выполнить и так долго обрабатывается.
А вообще, СПАСИБО. Если быстрее нельзя, то я так оставлю.
9 апр 08, 17:28    [5526214]     Ответить | Цитировать Сообщить модератору
 Re: Поможите select написать  [new]
12345вышелзайчикпогулять
Guest
автор
Медленно...


что оптимизатор говорит

включена оптимизация??

индексы есть по полям в конструкции where
+ бинарный на делетед

_screen.Cls()
SYS(3054,1)

create cursor tt (tt_id i, pp_id i)
insert into tt values (1, 1)
insert into tt values (1, 2)
insert into tt values (1, 3)
insert into tt values (2, 4)
insert into tt values (2, 5)
index on pp_id tag pp_id 
index on deleted() tag del binary

create cursor pp (pp_id i, value c(10))
insert into pp values (1, 'раз')
insert into pp values (2, 'два')
insert into pp values (3, 'три')
insert into pp values (4, 'четыре')
insert into pp values (5, 'пять')
index on pp_id tag pp_id
index on deleted() tag del binary

select t1.tt_id, ff(t1.tt_id)   ;
	from tt t1 					;
	group by t1.tt_id
	
	
function ff
lparameters tnId
local lcResult, lcValue
select value ;
	from pp t1 ;
		inner join tt t2 on t1.pp_id=t2.pp_id and t2.tt_id = tnId ;
	into array laArr
lcResult = ""
for each lcValue in laArr
	lcResult = lcResult + iif(!empty(lcResult),",","") + alltrim(lcValue)
endfor
return 	lcResult

сравни рез-ты
9 апр 08, 18:03    [5526473]     Ответить | Цитировать Сообщить модератору
 Re: Поможите select написать  [new]
12345вышелзайчикпогулять
Guest
вот так все будет полностью оптимизировано

при установке делетед в офф
необходимо дописывать
условие !dele()

_screen.Cls()
set deleted on
SYS(3054,1)

create cursor tt (tt_id i, pp_id i)
insert into tt values (1, 1)
insert into tt values (1, 2)
insert into tt values (1, 3)
insert into tt values (2, 4)
insert into tt values (2, 5)
index on pp_id tag pp_id 
index on tt_id tag tt_id 
index on deleted() tag del binary

create cursor pp (pp_id i, value c(10))
insert into pp values (1, 'раз')
insert into pp values (2, 'два')
insert into pp values (3, 'три')
insert into pp values (4, 'четыре')
insert into pp values (5, 'пять')
index on pp_id tag pp_id
index on deleted() tag del binary

select t1.tt_id, ff(t1.tt_id)   ;
	from tt t1 					;
	group by t1.tt_id
	
function ff
lparameters tnId
local lcResult, lcValue
select value ;
	from pp t1 ;
		inner join tt t2 on t1.pp_id=t2.pp_id and t2.tt_id = tnId ;
	into array laArr
lcResult = ""
for each lcValue in laArr
	lcResult = lcResult + iif(!empty(lcResult),",","") + alltrim(lcValue)
endfor
return 	lcResult
9 апр 08, 18:13    [5526545]     Ответить | Цитировать Сообщить модератору
 Re: Поможите select написать  [new]
Aleksey-K
Member

Откуда: Москва
Сообщений: 3116
Не очень понял, зачем в функции join ?
Может так будет быстрее:
CREATE CURSOR a1 (nomer I, Kvo I, name C(10))
INSERT INTO a1 VALUES (1,1,'a')
INSERT INTO a1 VALUES (1,4,'b')
INSERT INTO a1 VALUES (1,5,'v')
INSERT INTO a1 VALUES (2,2,'a')
INSERT INTO a1 VALUES (2,1,'d')
INSERT INTO a1 VALUES (2,2,'b')
INSERT INTO a1 VALUES (5,1,'c')
INSERT INTO a1 VALUES (5,1,'l')

SELECT nomer, SUM(Kvo) AS Kvo, ff(a1.nomer) AS name ;
	FROM a1 INTO CURSOR cur1 NOFILTER READWRITE ;
	GROUP BY nomer ;
	ORDER BY nomer

FUNCTION ff
	LPARAMETERS tnId
	LOCAL m.lcResult, m.lnI
	SELECT name FROM a1 INTO ARRAY laArr WHERE nomer = tnId ORDER BY name
	m.lcResult = ""
	FOR m.lnI = 1 TO ALEN(laArr)
		m.lcResult = m.lcResult + [,] + ALLTRIM(laArr[m.lnI])
	ENDFOR
	RETURN (m.lcResult)
ENDFUNC
Но... , не думаю, что использование в SELECT -SQL вместо агрегатной фунции UDF хороший вариант с точки зрения скорости. Это в SQL 2005 я могу написать на C# свою агрегатную функцию и через CLR использовать ее. Тогда агрегат будет считаться в потоке данных и не тормозить за счет многократных сканирований таблицы.
Может имеет смысл сделать запрос без заполнения последнего поля (конкатенации), а затем в цикле выполнять функцию ff:
SELECT nomer, SUM(Kvo) AS Kvo, CAST('' AS C(254)) AS name ;
	FROM a1 INTO CURSOR cur2 NOFILTER READWRITE ;
	GROUP BY nomer ;
	ORDER BY nomer
SELECT cur2
SCAN
	REPLACE name WITH ff(cur2.nomer)
ENDSCAN
В любом случае, индекс по полю nomer будет полезен.
Кстати, а какая длина строки ожидается после конкатенации? Если более 254 символов, то тогда только второй вариант но ...CAST('' AS M) AS name

С уважением, Алексей
10 апр 08, 09:44    [5528088]     Ответить | Цитировать Сообщить модератору
Все форумы / FoxPro, Visual FoxPro Ответить