Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Firebird, Interbase > Структура базы данных


Автор: MoreHate 23.6.2006, 06:35
Есть простенькая бухгалтерская программка. Есть такая вещь как "расход".
Расход = списания брака + денежная выручка

Если немного абстрагироваться, то получаются такие таблички:

Списания:
ID | Date | WareID | Sum

Выручки:
ID | Date | Sum

Выручка в день может быть только одна, а вот списаний - куча.

Так вот, нужно регулярно выводить таблицу Расхода в таком виде

Дата | Выручка | Сумма списаний за день | Общая сумма


Вопрос. Как лучше это осуществить?

Если по "правилам", то нужно все вычислять на лету. Т.е. если мы сделаем выборку хотя бы за месяц, то уже будет считаться 30 сумм таблицы "Списание".

Можно сделать быстрее, но уж больно криво, как мне кажется. Ввести таблицу "Расход"
в которой хранить данные за каждый день и обновлять её после каждого действия.
Примерно так:
ID | Date | Gain | AllowancesSum | Sum

Я весь в сомнениях smile 

Автор: Akina 23.6.2006, 08:01
Цитата(MoreHate @  23.6.2006,  07:35 Найти цитируемый пост)
Можно сделать быстрее, но уж больно криво, как мне кажется. Ввести таблицу "Расход", в которой хранить данные за каждый день и обновлять её после каждого действия.

Это называется "переопределенная база данных" и более чем настоятельно не рекомендуется.

Цитата(MoreHate @  23.6.2006,  07:35 Найти цитируемый пост)
Если по "правилам", то нужно все вычислять на лету. Т.е. если мы сделаем выборку хотя бы за месяц, то уже будет считаться 30 сумм таблицы "Списание".

Сколько записей за день? сто тысяч? миллион? что, всего сотня? бред какой... даже не заморачивайся - просто сделай индексированым поле даты, и все будет летать мухой. 

Автор: MoreHate 23.6.2006, 08:31
Спасибо. Так и сделаю. 

Автор: beroal 23.6.2006, 10:02
Считай не лету. Подоптимизировать можешь когда программа начнёт реально тормозить, но вероятность этого невелика. 

Автор: chief39 23.6.2006, 11:59
Если возникнет необходимость ускорения расчётов - можешь потом устроить дублирование данных(тысызыть скэшированные подсчёты). И использовать их, пеиодически обновляя. Но это только для действий без обратной связи. 
Например для отчётности месячной или ещё чего похуже. smile

Но без необходимости - не стоит. подсчитывай на лету. Кэшировать надо лишь в быстрых онлайн системах, где тысячи запросов на пересчёт могут замедлить отклик.

Вообще и то и то - практика нормальная, но второй вариант требует хорошего проектирования и аккуратности. да и то, при необходимости
 

Автор: MoreHate 24.6.2006, 09:19
Я думаю, это не будет оффтопом. Все-таки тема та же.

Код

SELECT A.A_DATE, SUM(A.A_SUM), G.G_DATE, SUM(G.GAIN) FROM OUT_ALLOWS A, OUT_GAINS G  GROUP BY A.A_DATE, G.G_DATE


Никак не могу сообразить, как можно соединить данные с двух таблиц по датам. Тут какая-то группировка хитрая? 

Автор: bas 24.6.2006, 11:42
А join не пробовал использовать, в нем наглядней соединения. 

Автор: beroal 24.6.2006, 13:15
Цитата(MoreHate @ 24.6.2006,  06:19)
Я думаю, это не будет оффтопом. Все-таки тема та же.

Код

SELECT A.A_DATE, SUM(A.A_SUM), G.G_DATE, SUM(G.GAIN) FROM OUT_ALLOWS A, OUT_GAINS G  GROUP BY A.A_DATE, G.G_DATE


Никак не могу сообразить, как можно соединить данные с двух таблиц по датам. Тут какая-то группировка хитрая?

Я думаю, лучше подзапросами. Сначала сгруппировать и суммировать, чтобы дата в обоих таблицах стала уникальной, потом соединять.
Код

SELECT DT, A_SUM1, GAIN1
FROM ( SELECT A_DATE AS DT, SUM(A_SUM) AS A_SUM1, 
  FROM OUT_ALLOWS
  GROUP BY A_DATE
) A
FULL JOIN ( SELECT G_DATE AS DT, SUM(GAIN) AS GAIN1
  FROM OUT_GAINS
  GROUP BY G_DATE
) G
ON A.DT = G.DT

 

Автор: MoreHate 25.6.2006, 12:57
beroal, не выполняется.

Или ошибка в запросе, или это особенности синтаксиса Firebird.

IbExpert выдал 
Dynamic SQL Error.
SQL error code = -104.
Token unknown - line 2, char 8.
SELECT.

Пойду почитаю мануал. Я с подзапросами слабо знаком. 

Автор: beroal 25.6.2006, 15:03
Я написал для MS SQL. В FireBird-е наверное можно выкрутиться, но лень думать. Я хотел дать общее представление об идее. 

Автор: MoreHate 25.6.2006, 16:44
Хм, в FireBird нет временных таблиц.

2Модератор: можно перекинуть вторую половину топика в форум по FireBird? Я думаю, что там помогут. 

Автор: LSD 25.6.2006, 19:06
Цитата(MoreHate @  25.6.2006,  17:44 Найти цитируемый пост)
2Модератор: можно перекинуть вторую половину топика в форум по FireBird? Я думаю, что там помогут.

Тогда уж весь топик, т.к. вторая половина без первой, будет непонятна. 

Автор: Alex 30.6.2006, 09:56
Какие временные таблицы, какие подзапросы, вы что людиииии....

Код

CREATE TABLE NEW_TABLE3 (
    ID     INTEGER NOT NULL,
    DATE1  DATE,
    "SUM"  INTEGER
);

INSERT INTO NEW_TABLE3 (ID, DATE1, "SUM") VALUES (1, '2006-06-30', 6);
INSERT INTO NEW_TABLE3 (ID, DATE1, "SUM") VALUES (2, '2006-06-30', 7);
INSERT INTO NEW_TABLE3 (ID, DATE1, "SUM") VALUES (3, '2006-06-29', 3);

CREATE TABLE NEW_TABLE4 (
    ID     INTEGER NOT NULL,
    DATE2  DATE,
    "SUM"  INTEGER
);

INSERT INTO NEW_TABLE4 (ID, DATE2, "SUM") VALUES (1, '2006-06-28', 9);
INSERT INTO NEW_TABLE4 (ID, DATE2, "SUM") VALUES (2, '2006-06-30', 7);


Запрос:
Код

SELECT
  case
    WHEN (t3.DATE1 is null) then t4.DATE2 else t3.DATE1
  end as date_sum
  ,SUM(t3."SUM") as sum_t3
  ,t4."SUM" as sum_t4
FROM NEW_TABLE3 t3 FULL JOIN NEW_TABLE4 t4 ON t3.DATE1 = t4.DATE2
GROUP By 1, 3


Результат
Цитата

DATE_SUM    SUM_T3    SUM_T4
28.06.2006     null             9
29.06.2006     3              null
30.06.2006     13              7



    

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)