Гость
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / SQL SELECT на М / 12 сообщений из 12, страница 1 из 1
04.03.2013, 17:26
    #38173614
SergeyLee
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
Критика приветствуется))) Поскольку не силен я в этом... Я знаю, что есть функция $Query, но не знаю как ей правильно пользоваться.
Где-то я нашел как можно переделать простой SQL SELECT запрос в М функцию и сделал так... (Надо найти ссылку где я такое нашел!).

Задача: SELECT field1,field2,... FROM table WHERE cond1=value1 AND cond2=value2 AND ...
Без JOIN, в условиях только AND, в списке полей может быть звездочка - *.

Я сделал М функцию: find(table,fields,conditions), fields - через разделитель, conditions - cond, через разделитель: cond - value

(Я не знаю как обвернуть правильно М код :(, сделаю его как С++ код)
Код: 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.
find(table,returns,conditions)
    ;
    Set returns=$piece(returns,$c(0))
    Set conditions=$piece(conditions,$c(0))
    ;
    ; CONDITIONS
    ; ищем есть ли ключевые условия (условия по ключу), пока что только primary
    Set conduniquename=""
    Set conduniquevalue=""
	Set condprimaryname=""
	Set condprimaryvalue=""
    For condI=1:1:($length(conditions,"~")/2) Do
    . Set condname(condI)=$piece(conditions,"~",(condI-1)*2+1)
    . Set condvalue(condI)=$piece(conditions,"~",(condI-1)*2+2)
    . Write "conditions: "_condI_" :: "_condname(condI)_" = "_condvalue(condI),!
    . ; проверка параметров - пустая строка? валидное имя поля? валидный тип значения?
    . Set t=$$checkvalue(table,condname(condI),"")
    . If t'=0 Quit "Error~"_t
    . If ^DB(table,condname(condI),"key")=1 Do
    . . Set condprimaryname=condname(condI)
    . . Set condprimaryvalue=condvalue(condI)
    . . Set condname(condI)=""
    . . Set condvalue(condI)=""
    . ; сохраняем ключ в элемент 0, очищаем текущий элемент (чтобы он не участвовал в фильтрации)
    . Else  Do
	. . If ^DB(table,condname(condI),"key")=2!(^DB(table,condname(condI),"key")=3) Do
	. . . If condprimaryname="" Do
    . . . . Set conduniquename=condname(condI)
    . . . . Set conduniquevalue=condvalue(condI)
    . . . . Set condname(condI)=""
    . . . . Set condvalue(condI)=""
    ;
    ; RETURNS	
    Set record=""
    Set result=""
    Set resultsCount=0
    ; RETURN VALUES
    If returns="*" Do
    . Set fieldDB="" For  Set fieldDB=$order(^DB(table,fieldDB)) Quit:fieldDB=""  Do
    . . If $data(^DB(table,fieldDB,"key"))=1 Set resultsCount=resultsCount+1
    Else  Do
    . For returnsId=1:1:$length(returns,"~") Do
    . . Set fieldreturns(returnsId)=$piece(values,"~",(returnsId))
    . . Write "return_values: "_returnsId,!
    . . ; проверка параметров - пустая строка? валидное имя поля? валидный тип значения?
    . . Set t=$$checkvalue(table,fieldreturns(returnsId),"")
	. . If t'=0 Quit "Error~"_t
    . . Set resultsCount=resultsCount+1
    ;
    ; следствие ведут знатоки
A2  Set condI=0
    ;Write "keyvalue = '"_condname(0)_"'",!
    ; primary key
	If condprimaryname'="" Do
	. Set record=condprimaryvalue
	. Write "record (pk): "_record,!
	Else  Do
	. ; unique key
	. If conduniquename'="" Do		; если есть ключевое условие
    . . Set record=$order(@("^"_table_"Indexes")@(conduniquename,conduniquevalue,record))
    . . Write "record (uk): "_conduniquename_" => "_conduniquevalue_" = "_record,!
    . Else  Do 					; если нет
    . . Set record=$order(@("^"_table)@(record))
    . . If writedebug=1 Write "record: "_record,!
    If record="" Goto B2
    ;
	; (only) primary key
	If condprimaryname'="",$length(conditions,"~")=2 Goto D2
	; (only) unique key
	If conduniquename'="",$length(conditions,"~")=2,^DB(table,conduniquename,"key")=2 Goto D2
	; no conditions
    If conditions="" Goto D2
    ; AND следующее условие
C2  Set condI=condI+1
    If condname(condI)'="",condvalue(condI)'="" Set testcond=$get(@("^"_table)@(record,condname(condI))) Write "condition: "_condname(condI)_" => "_condvalue(condI)_" ? "_testcond,!
    Else  Set testcond="" Write "no conditions: "_condI,! ; для прохождения проверки
    ;
    If testcond'=condvalue(condI) Goto A2
    Else  If condI<($length(conditions,"~")/2) Goto C2	; если проверка по условию прошла
    ;
D2  ; RETURN VALUES
    If returns="*" Do
    . Set fieldDB="" For  Set fieldDB=$order(^DB(table,fieldDB)) Quit:fieldDB=""  Do
    . . If $data(^DB(table,fieldDB,"key"))=1 Do
    . . . Set result=result_fieldDB_"~"_$get(@("^"_table)@(record,fieldDB))_"~"
    Else  Do
    . For returnsId=1:1:$length(returns,"~") Do
    . . Set result=result_fieldreturns(returnsId)_"~"_$get(@("^"_table)@(record,fieldreturns(returnsId)))_"~"
    ;
	If conduniquename'="",^DB(table,conduniquename,"key")=3 Goto A2
    If condprimaryname="",conduniquename="" Goto A2
    ;
B2  Quit resultsCount_"~"_result



Перебор по записям я сделал так как в примере, который я нашел... поищу ссылку... посредством Goto. Мне это не нравится!!!!!
Буду разбираться как схожую задачу решил некто Sean Woods здесь: https://github.com/seanwoods/reynard-gtm.
И мне не нужны решения ориентированные на Cache, только тру М.
Фух. Ангина и 37.8 градусов вынудили меня на это... :)
...
Рейтинг: 0 / 0
04.03.2013, 17:38
    #38173637
krvsa
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
Перейти на NoSql для делания SQL - верх непонятности...
...
Рейтинг: 0 / 0
04.03.2013, 17:39
    #38173638
Valeriu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
Сергей, попробуй связаться с этим человеком (Владимир Ильницкий)
[email=]v7ilnytskyy@yahoo.com
Он как раз модулем MQL и занимался в среде GT.M
Были у него и модули - все готовые !
...
Рейтинг: 0 / 0
04.03.2013, 18:01
    #38173669
SergeyLee
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
krvsaПерейти на NoSql для делания SQL - верх непонятности...
Будем отходить от SQL в сторону NoSQL. Эта тема больше относится к тому вопросу с чего начинать. И да, надо отталкиваться от GT.M/Cache/другой NoSQL базы данных. Но увы, пока отталкиваемся от сырого фронтэнда на PHP+MySQL.
...
Рейтинг: 0 / 0
04.03.2013, 18:56
    #38173721
SergeyLee
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
ValeriuСергей, попробуй связаться с этим человеком (Владимир Ильницкий)
[email=]v7ilnytskyy@yahoo.com
Он как раз модулем MQL и занимался в среде GT.M
Были у него и модули - все готовые !

Спасибо! :)
...
Рейтинг: 0 / 0
05.03.2013, 09:07
    #38174129
П.С.М.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
SergeyLee,

Код: sql
1.
2.
3.
    For condI=1:1:($length(conditions,"~")/2) Do
   // убрал лишнее
    . If t'=0 Quit "Error~"_t


Здесь строка If t'=0 Quit "Error~"_t выйдет только из тела цикла. Но это не выход из всей программы.
Аналогично и здесь
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
    Else  Do
    . For returnsId=1:1:$length(returns,"~") Do
    . . Set fieldreturns(returnsId)=$piece(values,"~",(returnsId))
    . . Write "return_values: "_returnsId,!
    . . ; проверка параметров - пустая строка? валидное имя поля? валидный тип значения?
    . . Set t=$$checkvalue(table,fieldreturns(returnsId),"")
    . . If t'=0 Quit "Error~"_t
    . . Set resultsCount=resultsCount+1


Строка If t'=0 Quit "Error~"_t - это выход из тела цикла. "Error~"_t возвращается в никуда :)
...
Рейтинг: 0 / 0
05.03.2013, 09:10
    #38174132
П.С.М.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
Вот посмотрите, что вернет функция
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
tmp(val)
 S val=$G(val,0)
 Q:'val val
 do
 . w !,"lvl1: ",val
 . I val>5 do
 . . w !,"lvl2: ",val
 . . I val>10 do
 . . . w !,"lvl3: ",val
 . . . I val>15 do
 . . . . w !,"lvl4: ",val
 . . . . Q "lvl4"
 . . . Q "lvl3"
 . . Q "lvl2"
 . Q "lvl1" 
 Q "end"
...
Рейтинг: 0 / 0
05.03.2013, 10:11
    #38174186
П.С.М.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
Я тут немножко замодернизировал :) По идее логика поменяться не должна.

Код: sql
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.
find(table,returns,conditions)
    ;
    New (table,returns,conditions)
    Set returns=$piece(returns,$c(0))
    Set conditions=$piece(conditions,$c(0))
    ;
    ; CONDITIONS
    ; ищем есть ли ключевые условия (условия по ключу), пока что только primary
    Set %err=""  ; 
    ; 
    Set conduniquename=""
    Set conduniquevalue=""
    Set condprimaryname=""
    Set condprimaryvalue=""
    For condI=1:1:($length(conditions,"~")/2) Do FIRST  Q:%err'=""
    ; RETURNS
    I %err'="" Q %err ; добавил выход	
    Set record=""
    Set result=""
    Set resultsCount=0
    ; RETURN VALUES
    If returns="*" Do SECOND
    Else  Do THIRD
    I %err'="" Q %err
    ; следствие ведут знатоки
 ;------------------------------------------------------------------------------ 
A2  Set condI=0
    ;Write "keyvalue = '"_condname(0)_"'",!
    ; primary key
	If condprimaryname'="" Do A21
	Else  Do A22
  If record="" Goto B2
    ;
	; (only) primary key
	If condprimaryname'="",$length(conditions,"~")=2 Goto D2
	; (only) unique key
	If conduniquename'="",$length(conditions,"~")=2,^DB(table,conduniquename,"key")=2 Goto D2
	; no conditions
  If conditions="" Goto D2
 ;------------------------------------------------------------------------------
 ; AND следующее условие
C2  Set condI=condI+1
    If condname(condI)'="",condvalue(condI)'="" D C21 
    Else  Set testcond="" Write "no conditions: "_condI,! ; для прохождения проверки
    ;
    If testcond'=condvalue(condI) Goto A2
    Else  If condI<($length(conditions,"~")/2) Goto C2	; если проверка по условию прошла
 ;------------------------------------------------------------------------------
D2  ; RETURN VALUES
  If returns="*" Do D21
  Else  Do D22
    ;
	If conduniquename'="",^DB(table,conduniquename,"key")=3 Goto A2
  If condprimaryname="",conduniquename="" Goto A2
 ;------------------------------------------------------------------------------
B2  
 Quit resultsCount_"~"_result
 ;------------------------------------------------------------------------------
FIRST      ; Можно метки назвать как-то более осмысленно
 Set condname(condI)=$piece(conditions,"~",(condI-1)*2+1)
 Set condvalue(condI)=$piece(conditions,"~",(condI-1)*2+2)
 Write "conditions: "_condI_" :: "_condname(condI)_" = "_condvalue(condI),!
 ; проверка параметров - пустая строка? валидное имя поля? валидный тип значения?
 Set t=$$checkvalue(table,condname(condI),"")
 ; было
 ;If t'=0 Quit "Error~"_t
 ; стало
 If t'=0 Set %err="Error~"_t Q
 If ^DB(table,condname(condI),"key")=1 Do FRST1 Q
 ; сохраняем ключ в элемент 0, очищаем текущий элемент (чтобы он не участвовал в фильтрации)
 ;Else  Do
 If '(^DB(table,condname(condI),"key")=2!(^DB(table,condname(condI),"key")=3)) Q
 If condprimaryname'="" Q
 Set conduniquename=condname(condI)
 Set conduniquevalue=condvalue(condI)
 Set condname(condI)=""
 Set condvalue(condI)=""
 Q
 ;------------------------------------------------------------------------------
FRST1        ; Первая метка в FIRST :)
 Set condprimaryname=condname(condI)
 Set condprimaryvalue=condvalue(condI)
 Set condname(condI)=""
 Set condvalue(condI)=""
 Q
 ;------------------------------------------------------------------------------
SECOND       ; вторая метка в гл. фнкц.
 Set fieldDB="" 
 For  Set fieldDB=$order(^DB(table,fieldDB)) Quit:fieldDB=""  Do SECOND1
 Q
 ;------------------------------------------------------------------------------
SECOND1
 If $data(^DB(table,fieldDB,"key"))=1 Set resultsCount=resultsCount+1
 Q
 ;------------------------------------------------------------------------------
THIRD
 For returnsId=1:1:$length(returns,"~") Do THIRD1 Q:%err'=""
 Q
 ;------------------------------------------------------------------------------
THIRD1
 Set fieldreturns(returnsId)=$piece(values,"~",(returnsId))
 Write "return_values: "_returnsId,!
 ; проверка параметров - пустая строка? валидное имя поля? валидный тип значения?
 Set t=$$checkvalue(table,fieldreturns(returnsId),"")
 ;If t'=0 Quit "Error~"_t
 If t'=0 Set %err="Error~"_t Q
 Set resultsCount=resultsCount+1
 Q
 ;------------------------------------------------------------------------------
A21
 Set record=condprimaryvalue
 Write "record (pk): "_record,!
 Q
 ;------------------------------------------------------------------------------
A22
 ; unique key
 If conduniquename'="" Do	A221 Q ; если есть ключевое условие
 Set record=$order(@("^"_table)@(record))
 If writedebug=1 Write "record: "_record,! 					; если нет
 Q
 ;------------------------------------------------------------------------------
A221
 Set record=$order(@("^"_table_"Indexes")@(conduniquename,conduniquevalue,record))
 Write "record (uk): "_conduniquename_" => "_conduniquevalue_" = "_record,!
 Q
 ;------------------------------------------------------------------------------
C21
 Set testcond=$get(@("^"_table)@(record,condname(condI))) 
 Write "condition: "_condname(condI)_" => "_condvalue(condI)_" ? "_testcond,!
 Q
 ;------------------------------------------------------------------------------
D21
 Set fieldDB="" For  Set fieldDB=$order(^DB(table,fieldDB)) Quit:fieldDB=""  Do D211
 Q
 ;------------------------------------------------------------------------------
D211
 If $data(^DB(table,fieldDB,"key"))'=1 Q
 Set result=result_fieldDB_"~"_$get(@("^"_table)@(record,fieldDB))_"~"
 Q
 ;------------------------------------------------------------------------------
D22
 For returnsId=1:1:$length(returns,"~") Set result=result_fieldreturns(returnsId)_"~"_$get(@("^"_table)@(record,fieldreturns(returnsId)))_"~"
 Q
 ;------------------------------------------------------------------------------



SergeyLee $Query, но не знаю как ей правильно пользоваться.
А в чем не понимание?
$Query позволяет пройти по всем узлам индексной переменной. Пример
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
tmp
 N
 S var("a")=""
 S var("a","b")=""
 s var("a","b","c")=""
 s var("a","b","c","d")=""
 S var("a","b","c","d","e")=""
 S var("a","b","c","d","e1")=""
 S var("a","b","c","d","e2")=""
 S var("a","b","c","d","e3")=""
 S var("a","b1")=""
 S var("a","b2")=""
 s val="var("""")"
 W "$query в прямом направлении",!
 F  s val=$Q(@val,1) Q:val=""  w val,!
 W !
 s val="var("""")"
 W "$query в обратном направлении",!
 F  s val=$Q(@val,-1) Q:val=""  w val,!
 Q


в то время как $order позволяет пробежать только по одному узелку.
...
Рейтинг: 0 / 0
05.03.2013, 11:50
    #38174342
SergeyLee
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
П.С.М.Я тут немножко замодернизировал :) По идее логика поменяться не должна.

Спасибо. Тоесть отказаться от уровней в пользу меток? Но тогда структура функции рвется, хотя может я просто привык к C++, C#. :) Попробую сейчас на практике.

Вот бы сделали (найти, сделать) туториал по типу http://learnyousomeerlang.com/ для MUMPS и GT.M/Cache. Хотя у GT.M и Cache достаточно документации. :) Но не хватает качественного туториала (не для чайников чтобы).
...
Рейтинг: 0 / 0
05.03.2013, 11:53
    #38174353
П.С.М.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
SergeyLee,

тут дело привычки. Я уже привык процедурки делать. ИМХО более читабельно получается.
...
Рейтинг: 0 / 0
05.03.2013, 12:06
    #38174386
П.С.М.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
[quot SergeyLee]П.С.М.Но тогда структура функции рвется.
Почему рвется?
Получается более компактная функция (легчечитаемая :))
сравните
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Fnc()
 N res
 S res=""
 D SOME
 F i=1:1:10 D CYCLE
 D SOMTHINGELSE
 Q res
SOME
 ; что-то делается
 Q
CYCLE
 ; и здесь что-то делается
 Q
SOMTHINGELSE
 ; ну и здесь что-то делается
 Q


или монолитная простыня с кучей всякого ветвления внутри
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Fnc()
 N res
 S res=""
 ; много чего делание
 I тра-та-та d
 . ; та-та
 . I да? D
 . . ; да-да
 F  d
 . ; что-то
 . . I что-то d
 . . . ; еще что-то
 ; и опять много чего-то
 Q res


Я не настаиваю, что используемый мной подход - это "истина в последней инстанции", просто я так привык и мне так удобнее :)
...
Рейтинг: 0 / 0
06.03.2013, 16:50
    #38176311
Бредятина
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SQL SELECT на М
SergeyLeeКритика приветствуется)))
...
И мне не нужны решения ориентированные на Cache, только тру М.
Цели должны быть высокие.
Вот Вам ориентир:

"... автор заявляет, что "наиболее мощной функциональной возможностью языка ConQuer... является го способность выполнять корреляции с произвольным уровнем сложности", и приводит пример:

#Работник1
..+-живет в Городе1
..+-родился в Стране1
..+-руководит работой Работника2, который
....+-живет в Гроде1
....+-родился в Стране2 <> Стране1

Этот запрос означает: "Извлечь данные о сотрудниках, руководящих работой других сотрудников, которые живут в том же городе, что и их руководитель, но родились в другой стране." Автор предлагает сформулировать этот запрос на SQL."

Вот это программируйте. Но, опять же, нужно понимать, что за ConQuer стоит технология моделирования - ОРМ (объектно-ролевое моделирование). Кстати, в ОРМ нет понятия свойства. И мы опять приходим к М2:) 13577413
...
Рейтинг: 0 / 0
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / SQL SELECT на М / 12 сообщений из 12, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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