powered by simpleCommunicator - 2.0.35     © 2025 Programmizd 02
Форумы / SQLite [игнор отключен] [закрыт для гостей] / VIEW с вычислением
14 сообщений из 14, страница 1 из 1
VIEW с вычислением
    #39507699
vict57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
приветствую уважаемое сообщество. делаю БД типа касса взаимопомощи (или общий котел)
Код: sql
1.
2.
CREATE TABLE "pays" ( `id` INTEGER, `user_id` INTEGER, `pay` TEXT, PRIMARY KEY(`id`) )
CREATE TABLE "users" ( `id` integer, `name` text, PRIMARY KEY(`id`) )


задача - вычислить общую сумму взносов, среднее и дебет/кредит каждого юзера
сделал VIEW
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
create view if not exists totals as
	select users.name as 'Имя',
	sum(pays.pay) as  'Взнос',
	(select sum(pay) from pays)/(select count(*) from users) as "Средний взнос",
	sum(pays.pay) - (select sum(pay) from pays)/(select count(*) from users) as "Итог"
	from users
	join pays
	on users.id=pays.user_id
	group by name;

	select * from totals;


работает, но смущает что повторяются вычисления (select sum(pay) from pays) и sum(pays.pay).
МОЖЕТ ЕСТЬ БОЛЕЕ РАЦИОНАЛЬНЫЙ МЕТОД?
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39507753
Фотография VSVLAD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vict57,

Плана "до"selectidorderfromdetail001SCAN TABLE pays010SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?)000USE TEMP B-TREE FOR GROUP BY000EXECUTE SCALAR SUBQUERY 1100SCAN TABLE pays000EXECUTE SCALAR SUBQUERY 2200SCAN TABLE users000EXECUTE SCALAR SUBQUERY 3300SCAN TABLE pays
План "после"selectidorderfromdetail100SCAN TABLE pays100USE TEMP B-TREE FOR GROUP BY100EXECUTE SCALAR SUBQUERY 2200SCAN TABLE pays001SCAN SUBQUERY 1 AS p010SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?)000USE TEMP B-TREE FOR ORDER BY

Сократилось на 1 скан таблицы pays, но появилась лишняя группировка. Надо смотреть на боевой базе, есть ли прогресс или регресс
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select users.name        as Имя,
	   p.pay             as Взнос,
	   p.avg_pay         as СреднийВзнос,
	   p.pay - p.avg_pay as Итог
from users
inner join ( select user_id,
                    sum(pay) pay,
                    (select sum(pay) / count(distinct user_id) pay from pays) avg_pay
             from pays
             group by user_id ) p on p.user_id = users.id
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39507850
vict57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
VSVLAD, спасибо за инфу.
у меня в SQL опыта мало, склоняюсь к мысли что БД лучше использовать чисто для поиска/хранения данных и фиксации изменений, а группировку и расчеты мне намного легче сделать в GUI клиента технически. или я не прав?
и не могли бы вы сказать чем смотрите план запроса? я пользуюсь SQLiteStudio, там план запроса совсем по-другому выглядит
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39507900
vict57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
с планом запроса разобрался:
Код: sql
1.
2.
explain query plan [select...]
explain [select...] 
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39509507
vict57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
пошел другим путем
делаю запрос
Код: sql
1.
select name,pay from users,pays where user.id=pays.user_id;


все необходимые вычисления делаю из этой таблицы на клиенте
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39513660
vict57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
в продолжение темы - нагуглил что в SQLite вместо переменных можно применять временные таблицы
запрос
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
drop table if exists pays_tmp;
create temp table pays_tmp(sum_pay text,avg_pay text);
insert into pays_tmp(sum_pay) values((select sum(pay) from pays));
insert into pays_tmp(avg_pay) values((select sum_pay from pays_tmp)/(select count(*) from users));
SELECT name Имя,
sum(pay) Взнос,
sum(pay) - (select avg_pay from pays_tmp) Итог
FROM users,pays where users.id = pays.user_id
GROUP BY name
union all
select '','Всего: '||(select sum_pay from pays_tmp),
'Среднее: '||((select avg_pay from pays_tmp));


будет ли этом метод менее ресурсоемким чем предыдущие?
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39513744
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vict57в продолжение темы - нагуглил что в SQLite вместо переменных можно применять временные таблицы
запросВ данном случае - зря. Строку "итого" проще посчитать на клиенте, пока вытягиваешь данные по основному резалтсету.
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39513924
vict57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl,
я пока не знаю, какой заказчик хочет клиент - Qt, Python или вебморду, оптимизирую скелет БД, поэтому все делаю запросами
как вообще тестируются БД - я создал тестовую базу на 100 юзеров по 10 платежей и смотрю по времени выполнения запроса, может есть средства для анализа?
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39514644
vict57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl,
Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE pays (id integer PRIMARY KEY , name text, pay numeric NOT NULL, date text DEFAULT (date()))
CREATE TABLE users (name text PRIMARY KEY)
CREATE TRIGGER add_pay AFTER INSERT ON pays 
BEGIN 
 select raise(abort,'Несуществующее имя') 
 where new.name not in (select name from users);
END


с учетом ваших замечаний
если изменить структуру БД так?
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39515275
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vict57White Owl,
я пока не знаю, какой заказчик хочет клиент - Qt, Python или вебморду, оптимизирую скелет БД, поэтому все делаю запросами
как вообще тестируются БД - я создал тестовую базу на 100 юзеров по 10 платежей и смотрю по времени выполнения запроса, может есть средства для анализа?Да какой бы клиент ни был. "Итого" все равно проще на нем считать.
К тому-же, если заказчик забыл сказать будет ли это десктопный клиент или веб клиент. Ты уверн что с этим заказчиком стоит работать?
И как можна забыть об этом спросить? Первый же вопрос заказчику: "чего вы хотите?"
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39515278
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vict57White Owl,
Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE pays (id integer PRIMARY KEY , name text, pay numeric NOT NULL, date text DEFAULT (date()))
CREATE TABLE users (name text PRIMARY KEY)
CREATE TRIGGER add_pay AFTER INSERT ON pays 
BEGIN 
 select raise(abort,'Несуществующее имя') 
 where new.name not in (select name from users);
END


с учетом ваших замечаний
если изменить структуру БД так?А это зачем??? Чем простые внешние ключи не устраивают?
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39515926
vict57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl,
работа как бы некоммерческая - я помогаю в школе вести комп класс преподу. дети решили скидываться кто сколько может и копить на всякие ардуины и т.п. препод хочет увлеченных развести на создание проги для учета взносов, а я изучаю SQLite чтобы дать задел. в программировании опыт есть, а БД плотно не занимался, поэтому извиняйте за глупые вопросы. до внешних ключей я еще не дочитал наверное.
Сама идея создание первичного текстового ключа имеет смысл? имхо если да то можно одним запросом обойтись
Код: sql
1.
2.
select name,sum(pay) from pays
group by name
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39515955
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vict57White Owl,
работа как бы некоммерческая - я помогаю в школе вести комп класс преподу. дети решили скидываться кто сколько может и копить на всякие ардуины и т.п. препод хочет увлеченных развести на создание проги для учета взносов, а я изучаю SQLite чтобы дать задел. в программировании опыт есть, а БД плотно не занимался, поэтому извиняйте за глупые вопросы.
Вообще-то, разработка начинается с хотелки: "хочу чтобы на экране было это, и оно делало то-то". Из этого решается какая будет общая архитектура продукта (десктоп приложение, клиент-сервер с тонким или толстым клиентом, или вообще что-то узкоспециализированное).
Для учета платежей вам хватит экселевского листа. Полноценная СУБД там не нужна.
Если делать это на основе ардуино, то это уже что-то граничащее с собственным платежным терминалом получится. Задачка вполне себе ученическая, но все-же уровня института.


vict57Сама идея создание первичного текстового ключа имеет смысл? Да, конечно.
...
Рейтинг: 0 / 0
VIEW с вычислением
    #39515975
vict57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White Owl,

технически я такую работу напишу на C++/Qt без напряга за день примерно и без баз данных совсем,
но для детей на данном этапе это будет сложно - отобьет все желание к программированию.
задача - научить детей создавать свое что-то , а не учить их пользоваться Excel.
sorry за оффтоп
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / SQLite [игнор отключен] [закрыт для гостей] / VIEW с вычислением
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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