powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / %INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
11 сообщений из 11, страница 1 из 1
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37005967
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пример возьмем из соседнего топика про суперфильм (я про соцсеть ;):

Допустим, есть объект "Человек", пусть в примере айди человека 55
у него туча свойств типа "Человек" (супруг 78, дети 102,126,184, родители 5,7, друзья 77,64)
и некое расчетное свойство "ближний_круг" - куда в виде листа сваливаются его айдишник вкупе с айдишниками всех его друзей/родственников $lb(55,78,102,126,...)

Есть объект "Клуб", содержащий объекты "Член" (простите мой французский), ссылающиеся на "Человека"

ЗАДАЧА: Для ограниченного набора "Членов", например, для "любителей подводного лова" получить информацию о "Человеках" их близкого окружения. Например, список фамилий и цвет волос (почему бы и нет...).

JOIN по-простому прикрутить не могу не подходит. Но памятуя, что JOIN лежит на одной полочке с IN, решение представлял таким:

1. Поскольку список всей родни всех рыбаков, по-сути есть список списков, а нас интересует просто список, понадобится преобразование вида

Код: plaintext
1.
2.
3.
&sql(SELECT LIST($listtostring(Человек->ближний_круг))
 INTO :список_родни_рыбаков
 FROM Член WHERE входит_в_число_любителей_зимней_рыбалки =  1 
)	

В переменной список_родни_рыбаков окажется то, что там и должно оказаться ;) Уверен, что есть более красивые варианты, но я их не знаю ;(

2. С учетом того, что речь идет о зене, далее нужно сформировать условие для прорисовки таблицы. И для условия есть два варианта:
Код: plaintext
1.
s table.whereClause = "ID IN ("_список_родни_рыбаков_")"
s table.whereClause = "ID %INLIST($listbuild("_список_родни_рыбаков_"))"
В первом случае запрос выполняется крайне медленно.
Во втором для больших групп выходит сообщение ...<MAXSTRING>removeRedundant+14^%qaqpre2 ...
Откуда ноги растут, примерно понятно. А вот как обойти - не очень.
Может, кто в курсе, что неправильно в запросе вида:
Код: plaintext
1.
2.
3.
SELECT ФИО, цвет_волос FROM Человек WHERE ID %INLIST(
$listbuild(SELECT LIST($listtostring(Человек->ближний_круг))
 FROM Член WHERE входит_в_число_любителей_зимней_рыбалки =  1 )
)
Ибо портал выдает ошибку:
"ОШИБКА #5540: SQLCODE: -12 Сообщение: Ожидается конструкция, начинающаяся с: идентификатора, константы, агрегата, $$, (, :, +, -, %ALPHAUP, %EXACT, %MVR %SQLSTRING, %SQLUPPER, %STRING или %UPPER ^ SELECT <купюра> %INLIST ( $ listbuild ( SELECT<именно в этом месте текст ошибки обрывается>"
?
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37005987
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesovА вот как обойти - не очень.
Как вариант, вместо IN - хранимая процедура. Которая просто вернёт истину или ложь для некой записи таблицы...
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37005989
Фотография krvsa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesov , т.е. идея такая - все "длинное" заменить на нечто "короткое". До тех пор, пока (как минимум) данная ошибка не уйдёт...
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37006061
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Размер списка ограничен (~32Kb), так же как и размер текста запроса.
Проще и гибче будет, если "ближний_круг" окажется не списком людей, а курсором.
Тогда можно будет написать, что-то типа:
Код: plaintext
1.
SELECT ФИО, цвет_волос FROM Человек WHERE ID IN 
(SELECT Человек->ближний_круг FROM Член WHERE входит_в_число_любителей_зимней_рыбалки =  1 )
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37009543
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servitРазмер списка ограничен (~32Kb), так же как и размер текста запроса.
Проще и гибче будет, если "ближний_круг" окажется не списком людей, а курсором.
Тогда можно будет написать, что-то типа:
Код: plaintext
1.
SELECT ФИО, цвет_волос FROM Человек WHERE ID IN 
(SELECT Человек->ближний_круг FROM Член WHERE входит_в_число_любителей_зимней_рыбалки =  1 )

Это первое, что и пришло в голову... Да есть проблемка небольшая - в результат попадают лишь те данные, где "ближний_круг" состоит ТОЛЬКО из айди рыбака (проще говоря, когда рыбачок один-одинешенек на свете). То-то я удивился, когда вернулось очень мало записей...
Это и понятно, получается WHERE ID IN ("55", "56,67,123", "78,144" etc.). Вот и попадет только 55 в выборку.
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37009547
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
krvsakolesovА вот как обойти - не очень.
Как вариант, вместо IN - хранимая процедура. Которая просто вернёт истину или ложь для некой записи таблицы...Один из аспектов проблемы- замена "IN" на "%INLIST", ибо второй работает ощутимо быстрее... Но, похоже лишь с довольно ограниченными листами. Противоречие: вроде листы по размеру не ограничены, а %INLIST в качестве аргумента принимает только коротенькие... этакие $listik ($listochechek). В общем и целом резюмирую:
Не пытайтесь сделать что-то сложнее табуретки используя Intersystems Cache' .
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37009551
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesovservitРазмер списка ограничен (~32Kb), так же как и размер текста запроса.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
USER>s l = $lb() f i =  1 : 1 : 8255  {s l= l_$lb(i)} w $l(l)
 32766 
USER>s l = $lb() f i =  1 : 1 : 8256  {s l= l_$lb(i)} w $l(l)
 
S l = $LB() F i =  1 : 1 : 8256  {S l= l_$LB(i)} W $L(l)
                            ^
<MAXSTRING>
USER>
И правда что...
Вот же подстава... А уж как разрекламировали этот %INLIST... а он - так себе ;)
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37009585
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не пытайтесь сделать что-то сложнее табуретки используя извращенные методы, не понимая принципов устройства или имея кривые руки.

Если бы вы знали, что список это строка, у вас даже мысли бы не возникло использовать его для таких целей.
Для доступа к элементу списка при условии, что список состоит из N элементов нужно в среднем N/2 итераций.

У вас ошибка в проектировании. Не могут дети быть свойствами человека.
Я сейчас скажу слово "связи" - и придет злой бабай, объяснит вам, как вы неправы.
Правда он скажет, что их вообще нет в ни в каше ни вообще в SQL, но это уже вопрос интерпретации.

У вас задача довольно простая и решается средствами SQL

Такие таблицы
Человек - (Человек) - люди
Родня - (Человек, Человек2, Тип родства) - родственники
Клуб -(Клуб)
Члены клуба -(Клуб, Человек) - члены клуба
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37009750
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesovВот же подстава... А уж как разрекламировали этот %INLIST... а он - так себе ;)%INLIST делает ровно то, на что был рассчитан.
Я им часто пользуюсь, когда уверен в небольшом размере списка или обрабатываю поля-списки (вместо FOR SOME %ELEMENT ):
Код: plaintext
1.
2.
3.
4.
class ...
{
Property lst1 As list Of %String(MAXLEN= 1 ,MINLEN= 1 );
Property lst2 As list Of %String(MAXLEN= 8000 ,MINLEN= 8000 );
}
kolesovЭто и понятно, получается WHERE ID IN ("55", "56,67,123", "78,144" etc.). Вот и попадет только 55 в выборку."56,67,123" - это не курсор.

PS: всё зависит от проектирования структуры классов. Имея её, можно было бы дать более конкретный ответ, а пока так:
Код: plaintext
1.
2.
3.
SELECT Человек2->ФИО,Человек2->цвет_волос FROM Родня 
WHERE
  тип_родства IN (кум,брат,сват,...) AND
  Человек IN (SELECT Человек FROM Член WHERE входит_в_число_любителей_зимней_рыбалки =  1 )
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37010434
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блок А.Н.У вас ошибка в проектировании.
Ха. Я взял данную структуру в качестве примера (см. начало топика).
Вдаваться в реальные подробности моих структур данных в данном случае не считаю нужным. Задачи, подобные приведенной, существуют независимо от того, есть ли у меня ошибки в проектировании ;)
Собственно, уперся в ограничение размера списка. Значит, остается использовать IN или JOIN.
...
Рейтинг: 0 / 0
%INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
    #37012251
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesov, SQL развращает ...
Код: 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.
/// Допустим, есть объект "Человек"
Class User.Man Extends (%Persistent, %Populate) {
/// супруг/а
Property spouse As User.Man;
/// дети 
Property childs As list Of User.Man;
/// родители
Property parents As list Of User.Man;
/// друзья
Property friends As list Of User.Man;
/// Фамилия
Property name As %String;
/// Цвет волос
Property colorhead As %String;

/// некое расчетное свойство "ближний_круг" куда в виде листа сваливаются его айдишник 
/// вкупе с айдишниками всех его друзей/родственников 
/// doublefint: база отлично ищет и без списков
ClassMethod IsInAround(id As %String, testId As %String) As %Boolean [ SqlProc ] {
	 q:'..%ExistsId(id) 0  q:'..%ExistsId(testId)  0 
	 q:..spouseGetStored(id)=testId  1 
	 ;может дети?
	 &sql(SELECT childs Into :cid From SQLUser.Man_childs Where Man=:id And childs=:testId)
	 Q:'SQLCODE 1
	 ;может родители?
	 &sql(SELECT parents Into :pid From SQLUser.Man_parents Where Man=:id And parents=:testId)
	 Q:'SQLCODE  1 
	 ;или друзья ?
	 &sql(SELECT friends Into :fid From SQLUser.Man_friends Where Man=:id And friends=:testId) 
	 Q:'SQLCODE  1 
	 Q  0 
}

<Storage name="Default">
<Data name="ManDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>spouse</Value>
</Value>
<Value name="3">
<Value>name</Value>
</Value>
<Value name="4">
<Value>colorhead</Value>
</Value>
</Data>
<Data name="childs">
<Attribute>childs</Attribute>
<Structure>subnode</Structure>
<Subscript>"childs"</Subscript>
</Data>
<Data name="friends">
<Attribute>friends</Attribute>
<Structure>subnode</Structure>
<Subscript>"friends"</Subscript>
</Data>
<Data name="parents">
<Attribute>parents</Attribute>
<Structure>subnode</Structure>
<Subscript>"parents"</Subscript>
</Data>
<DataLocation>^User.ManD</DataLocation>
<DefaultData>ManDefaultData</DefaultData>
<ExtentSize> 100000 </ExtentSize>
<IdLocation>^User.ManD</IdLocation>
<IndexLocation>^User.ManI</IndexLocation>
<StreamLocation>^User.ManS</StreamLocation>
<Type>%Library.CacheStorage</Type>
</Storage>
Немного упростил...
Код: 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.
/// "Клуб", содержащий объекты "Член", ссылающиеся на "Человека"
Class User.Club Extends (%Persistent, %Populate)
{
/// например, "любителей подводного лова" 
Property name As %String;
/// члены клуба
Property members As list Of User.Man;

/// например, для "любителей подводного лова" получить информацию о "Человеках" их близкого окружения. 
Query taburet4Kolesov(clubId As %String) As %SQLQuery {
	Select members,Man.ID as mid, Man.name as mname, colorhead
	From club_members Inner Join Man on Man_IsInAround(members,Man.ID)= 1 
	Where club= 1 
}

<Storage name="Default">
<Data name="ClubDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>name</Value>
</Value>
</Data>
<Data name="members">
<Attribute>members</Attribute>
<Structure>subnode</Structure>
<Subscript>"members"</Subscript>
</Data>
<DataLocation>^User.ClubD</DataLocation>
<DefaultData>ClubDefaultData</DefaultData>
<ExtentSize> 1000 </ExtentSize>
<IdLocation>^User.ClubD</IdLocation>
<IndexLocation>^User.ClubI</IndexLocation>
<StreamLocation>^User.ClubS</StreamLocation>
<Type>%Library.CacheStorage</Type>
</Storage>
}
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / %INLIST() vs. IN() = <MAXSTRING>!? (и немного zen)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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