База данных "Фирма вторсырья".
| Название таблицы | Поля таблицы |
| Income_o | (point, date, inc) |
| Outcome_o | (point, date, out) |
| Income | (code, point, date, inc) |
| Outcome | (code, point, date, out) |
Фирма имеет несколько пунктов приема вторсырья. Каждый пункт получает деньги для их выдачи сдатчикам вторсырья. Сведения о получении денег на пунктах приема записываются в таблицу:
Income_o(point, date, inc)
Первичным ключом является (point, date). При этом в столбец date записывается только дата (без времени), т.е. прием денег (inc) на каждом пункте производится не чаще одного раза в день. Сведения о выдаче денег сдатчикам вторсырья записываются в таблицу:
Outcome_o(point, date, out)
В этой таблице также первичный ключ (point, date) гарантирует отчетность каждого пункта о выданных деньгах (out) не чаще одного раза в день.
В случае, когда приход и расход денег может фиксироваться несколько раз в день, используется другая схема с таблицами, имеющими первичный ключ code:
Income(code, point, date, inc)
Outcome(code, point, date, out)
Здесь также значения столбца date не содержат времени.
Разминка:
SELECT i.*, o.out # из таблицы income выведутся все поля, а из outcome - только поле out FROM income i LEFT JOIN outcome o ON i.point=o.point AND i.date=o.date
Задание 29:
В предположении, что приход и расход денег на каждом пункте приема фиксируется не чаще одного раза в день [т.е. первичный ключ (пункт, дата)], написать запрос с выходными данными (пункт, дата, приход, расход). Использовать таблицы Income_o и Outcome_o.
SQL-запрос 29:
SELECT t1.point, t1.date, inc, out FROM income_o t1 LEFT JOIN outcome_o t2 ON t1.point = t2.point AND t1.date = t2.date UNION SELECT t2.point, t2.date, inc, out FROM income_o t1 RIGHT JOIN outcome_o t2 ON t1.point = t2.point AND t1.date = t2.date
Задание 30:
В предположении, что приход и расход денег на каждом пункте приема фиксируется произвольное число раз (первичным ключом в таблицах является столбец code), требуется получить таблицу, в которой каждому пункту за каждую дату выполнения операций будет соответствовать одна строка.
Вывод: point, date, суммарный расход пункта за день (out), суммарный приход пункта за день (inc).
Отсутствующие значения считать неопределенными (NULL).
SQL-запрос 30:
SELECT point, date, SUM(sum_out), SUM(sum_inc)
FROM (
SELECT point, date, SUM(inc) AS sum_inc, null AS sum_out
FROM Income
GROUP BY point, date
UNION
SELECT point, date, null AS sum_inc, SUM(out) AS sum_out
FROM Outcome
GROUP BY point, date) AS T
GROUP BY point, date
ORDER BY point
Задание 59:
Посчитать остаток денежных средств на каждом пункте приема для базы данных с отчетностью не чаще одного раза в день.
Вывод: пункт, остаток.
SQL-запрос 59:
WITH T AS (
SELECT t1.point, t1.date, inc, out
FROM income_o t1
LEFT JOIN outcome_o t2
ON t1.point = t2.point
AND t1.date = t2.date
UNION
SELECT t2.point, t2.date, inc, out
FROM income_o t1
RIGHT JOIN outcome_o t2
ON t1.point = t2.point
AND t1.date = t2.date
)
SELECT point, SUM(
CASE WHEN inc IS NULL
THEN
CASE WHEN out IS NULL
THEN 0
ELSE 0 - out
END
ELSE
CASE WHEN out IS NULL
THEN inc
ELSE inc - out
END
END
)
FROM T
GROUP BY point
Задание 60:
Посчитать остаток денежных средств на начало дня 15/04/01 на каждом пункте приема для базы данных с отчетностью не чаще одного раза в день.
Вывод: пункт, остаток.
Замечание. Не учитывать пункты, информации о которых нет до указанной даты.
SQL-запрос 60:
WITH T AS (
SELECT t1.point, t1.date, inc, out
FROM income_o t1
LEFT JOIN outcome_o t2
ON t1.point = t2.point
AND t1.date = t2.date
UNION
SELECT t2.point, t2.date, inc, out
FROM income_o t1
RIGHT JOIN outcome_o t2
ON t1.point = t2.point
AND t1.date = t2.date
)
SELECT point, SUM(
CASE WHEN inc IS NULL
THEN
CASE WHEN out IS NULL
THEN 0
ELSE 0 - out
END
ELSE
CASE WHEN out IS NULL
THEN inc
ELSE inc - out
END
END
)
FROM T
WHERE date < CONVERT(date, '15.04.2001', 104)
GROUP BY point
Задание 61:
Посчитать остаток денежных средств на всех пунктах приема для базы данных с отчетностью не чаще одного раза в день.
SQL-запрос 61:
SELECT SINC - SOUT FROM (
SELECT SUM(inc) AS SINC FROM income_o
) AS T1, (
SELECT SUM(out) AS SOUT FROM outcome_o
) AS T2
SELECT SINC - SOUT FROM (
SELECT SUM(
CASE WHEN inc IS NULL
THEN 0
ELSE inc
END
) AS SINC FROM income_o
) AS T1, (
SELECT SUM(
CASE WHEN out IS NULL
THEN 0
ELSE out
END
) AS SOUT FROM outcome_o
) AS T2
Задание 62:
Посчитать остаток денежных средств на всех пунктах приема на начало дня 15/04/01 для базы данных с отчетностью не чаще одного раза в день.
SQL-запрос 62:
SELECT SINC - SOUT FROM (
SELECT SUM(inc) AS SINC FROM income_o
WHERE date < CONVERT(date, '15.04.2001', 104)
) AS T1, (
SELECT SUM(out) AS SOUT FROM outcome_o
WHERE date < CONVERT(date, '15.04.2001', 104)
) AS T2
Задание 64:
Используя таблицы Income и Outcome, для каждого пункта приема определить дни, когда был приход, но не было расхода и наоборот.
Вывод: пункт, дата, тип операции (inc/out), денежная сумма за день.
SQL-запрос 64:
WITH T AS (
SELECT t1.point, t1.date, inc, out
FROM income t1
LEFT JOIN outcome t2
ON t1.point = t2.point
AND t1.date = t2.date
UNION
SELECT t2.point, t2.date, inc, out
FROM income t1
RIGHT JOIN outcome t2
ON t1.point = t2.point
AND t1.date = t2.date
)
SELECT point, date, (
CASE WHEN (inc IS NULL AND out IS NOT NULL)
THEN 'out'
ELSE CASE WHEN (inc IS NOT NULL AND out IS NULL)
THEN 'inc'
ELSE 'bad' END
END
) AS TYPE, (
CASE WHEN (inc IS NULL AND out IS NOT NULL)
THEN out
ELSE CASE WHEN (inc IS NOT NULL AND out IS NULL)
THEN inc
ELSE 0 END
END
) AS MONEY FROM T
WHERE (inc IS NULL AND out IS NOT NULL)
OR (inc IS NOT NULL AND out IS NULL)
