Агрегирование по статусу и перекрестное присоединение к подзапросу с получением общего количества для расчета процента. Для переименования и пользовательского заказа вы можете использовать CASE
с.
SELECT cs.s data,
cs.c / ca.c * 100 value
FROM (SELECT CASE client_status
WHEN 'BAD DEPT' THEN
1
WHEN 'ALERT' THEN
2
WHEN 'REMIND BAYAR' THEN
2
WHEN 'RUTIN BAYAR' THEN
4
WHEN 'POTENSI KOREKSI' THEN
5
WHEN 'TOP 10' THEN
6
END o,
CASE client_status
WHEN 'BAD DEPT' THEN
'Bad'
WHEN 'ALERT' THEN
'Alert'
WHEN 'REMIND BAYAR' THEN
'Remind'
WHEN 'RUTIN BAYAR' THEN
'Rutin'
WHEN 'POTENSI KOREKSI' THEN
'Potensi'
WHEN 'TOP 10' THEN
'Top'
END s,
count(*) c
FROM clients
GROUP BY client_status) cs
CROSS JOIN (SELECT count(*) c
FROM clients) ca
ORDER BY cs.o;
Функция, которая выделяет память, вызывается несколько раз. Адрес вызывающей стороны указывает на код, который сделал выделение, и тот код просто выполняется несколько раз.
Вот пример в C:
void *allocate (void)
{
return (malloc(1000));
}
int main()
{
mtrace();
allocate();
allocate();
}
Вывод от mtrace:
Memory not freed: ----------------- Address Size Caller 0x0000000000601460 0x3e8 at 0x4004f6 0x0000000000601850 0x3e8 at 0x4004f6
Отметьте, как адрес вызывающей стороны идентичен? Поэтому mtrace, анализ сценария говорит, что они идентичны, потому что та же ошибка замечается больше что однажды, приводя к нескольким утечкам памяти.
Компиляция с флагами отладок (-g) полезна, если Вы можете:
Memory not freed: ----------------- Address Size Caller 0x0000000000601460 0x3e8 at /home/andrjohn/development/playground/test.c:6 0x0000000000601850 0x3e8 at /home/andrjohn/development/playground/test.c:6
Вы смотрите на прямой вывод mtrace, который чрезвычайно сбивает с толку и парадоксален. К счастью существует сценарий жемчуга (названный mtrace, найденным в glibc-utils), который может очень легко помочь парсингу этого вывода.
Скомпилируйте свою сборку с отладкой на и выполните mtrace как такой:
$ gcc -g -o test test.c
$ MALLOC_TRACE=mtrace.out ./test
$ mtrace test mtrace.out
Memory not freed:
-----------------
Address Size Caller
0x094d9378 0x400 at test.c:6
Вывод должен быть намного легче к обзору.
Попытайтесь запустить свое приложение под valgrind. Это могло бы высказать Вам лучшее мнение о том, что на самом деле пропускается.
Одно возможное объяснение состоит в том, что та же функция выделяет различные буферные размеры? Одним таким примером является strdup.
Для второго вопроса возможно, что время выполнения выделяет некоторую "статическую" область царапины, которая не предназначается, чтобы быть освобожденной, пока процесс не завершается. И в той точке, ОС будет очистка после процесса так или иначе.
Думайте об этом этот путь: в Java нет никаких деструкторов и никаких гарантий, что завершение будут когда-либо называть для любого объекта.