powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / интересные факты / наблюдения / анализ чужих и собственных решений
5 сообщений из 280, страница 12 из 12
интересные факты / наблюдения / анализ чужих и собственных решений
    #38823452
guest_rusimport
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
\\\\guest_rusimport, очень спорное решение. Гораздо проще получить строку через ADO (GetString), ИМХО.
не понял , а спорить то тут о чем ? :) есть такой вариант , и он работает :)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38823541
\\\\
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
guest_rusimport...не понял , а спорить то тут о чем ? ...Это не спор, это (см. название топика) анализ чужих решений... ;-)
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #38823846
guest_rusimport
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
\\\\,
ну, тогда уж надо было указать достоинства , недостатки, сравнить с другими вариантами :)
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
интересные факты / наблюдения / анализ чужих и собственных решений
    #39927121
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для решения одной специфической задачи мне пришлось группировать записи и умножить значения, а не просуммировать. Дело в том, что существует агрегатная функция суммирования (SUM), а вот умножения (Multiply) – нет. Как быть?
Есть несколько способов решения данной задачи.

Вариант №1.
Нужно в VBA функции динамически создать SQL текст запроса (перебирая циклом) и перед запуском самого запроса подменить текст. Что-то вроде этого:
Код: sql
1.
2.
3.
4.
SELECT * FROM
(SELECT 1 AS ID, 2*115*17 AS RESULT FROM MSysObjects WHERE ID = 2
UNION ALL SELECT 2 AS ID, 19*13 AS RESULT FROM MSysObjects WHERE ID = 2
UNION ALL SELECT 3 AS ID, 24*10*15*7 AS RESULT FROM MSysObjects WHERE ID = 2) AS Data


Данный метод хорош, когда речь идёт о сравнительно небольшом количестве записей. Если же речь идёт о сотни тысяч, а то и более записей, то этот метод не годится. Во-первых, слишком долго будет программа обрабатывать циклом записи и во-вторых, SQL текст запроса не бесконечный, миллион символов не переварит.

Вариант №2.
Создаём VBA функцию, которая циклом перебирает значения по указанному ID и умножает значения. А в тексте запроса просто указываем название VBA функции. Метод хорош, но для большого количества записей будет требовать много времени на обработку.

Вариант №3.
Создаём VBA функцию, которая также циклом перебирает значения по указанному ID и превратив числовое значение в текстовое будет сцеплять их. Что-то вроде «2*115*17» для каждого ID. А в тексте запроса указываем название VBA функции, при этом обернув полученное значение дополнительной функцией EVAL. Этот метод хуже, чем вариант №2. Кроме того, из-за режима «печосницы» (SandboxMode) функция EVAL может и не работать у всех.

Вариант №4.
На просторах интернета я встретил самую необычную и изящную идею. Тот, кто додумался до этого, просто гений! Я бы сам никогда не додумался. Метод настолько очаровал меня, что я решил поделиться им. Оказывается агрегатной функции SUM вполне достаточно! Но вот только придётся изощряться. Дело в том, что сумма логарифмов с одинаковым основанием равняется как раз таки логарифму точно с таким основанием, но с умножением значений. Т.е.:
LN(A1) + LN(A2) + … + LN(An) = LN(A1*A2*…*An)
Чтобы избавиться от логарифма полученное таким образом значение потом нужно будет воздвигать в степень e.
Правда тут есть нюансы: все умножаемые числа должны быть больше 0, а для этого придётся брать только абсолютное значение и параллельно ввести учёт знаков. Ну и в случае нулевого значения добавить «костыль».
И так. Чтобы было более понятно о чём речь создаём таблицу в VBA и добавляем тестовые значения.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Sub Test()
  CurrentDb.Execute "CREATE TABLE Test (ID Long, Val Double)"
  CurrentDb.Execute "INSERT INTO Test (ID, Val)" & vbCrLf & _
    "SELECT * FROM" & vbCrLf & _
    "(SELECT 1 AS ID, 2 AS Val FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 1, 115 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 1, -17 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 2, 19 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 2, 13 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 3, 24 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 3, 10 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 3, 15 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 3, 7 FROM MSysObjects WHERE ID = 2" & vbCrLf & _
    "UNION ALL SELECT 4, 0 FROM MSysObjects WHERE ID = 2) AS Data"
End Sub


Вот теперь и запускаем вот такой запрос:
Код: sql
1.
2.
3.
4.
SELECT ID, EXP(SUM(LOG(ABS(IIf(Val=0, 1, Val))))) * (-1)^(SUM(IIf(Val<0,1,0))) * MIN(IIf(Val=0, 0, 1)) AS Mulltiply
FROM Test
GROUP BY ID
ORDER BY 1;


Выражение « (-1)^(SUM(IIf(Val<0,1,0))) » необходимо чтобы следить за знаком (в случае если окажется отрицательное число).
Выражение « MIN(IIf(Val=0, 0, 1)) » необходимо для выяснения нет ли 0 среди умножаемых значений.
Как то так.
...
Рейтинг: 0 / 0
интересные факты / наблюдения / анализ чужих и собственных решений
    #39927123
studieren
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если Вы точно знаете, что среди значений нет нуля и все числа всегда положительные, то и текст запроса будет проще.
Код: sql
1.
2.
3.
4.
SELECT ID, EXP(SUM(LOG(Val))) AS Mulltiply
FROM Test
GROUP BY ID
ORDER BY 1;



P.S.
Конечно же нужно учесть при этом, что если умножаемых чисел слишком много или же сами числа достаточно огромные, то может возникнуть ошибка переполнения.
...
Рейтинг: 0 / 0
5 сообщений из 280, страница 12 из 12
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / интересные факты / наблюдения / анализ чужих и собственных решений
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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