Вложенный запрос может сделать задание.
SELECT author_last_name, dewey_number, NumOccurrences
FROM author INNER JOIN
( SELECT author_id, dewey_number, COUNT(dewey_number) AS NumOccurrences
FROM book
GROUP BY author_id, dewey_number
HAVING ( COUNT(dewey_number) > 1 ) ) AS duplicates
ON author.id = duplicates.author_id
(я не знаю - ли это самый быстрый способ достигнуть того, что Вы хотите.)
Обновление: Здесь мои данные
SELECT * FROM author;
id | author_last_name
----+------------------
1 | Fowler
2 | Knuth
3 | Lang
SELECT * FROM book;
id | author_id | dewey_number | title
----+-----------+--------------+------------------------
1 | 1 | 600 | Refactoring
2 | 1 | 600 | Refactoring
3 | 1 | 600 | Analysis Patterns
4 | 2 | 600 | TAOCP vol. 1
5 | 2 | 600 | TAOCP vol. 1
6 | 2 | 600 | TAOCP vol. 2
7 | 3 | 500 | Algebra
8 | 3 | 500 | Undergraduate Analysis
9 | 1 | 600 | Refactoring
10 | 2 | 500 | Concrete Mathematics
11 | 2 | 500 | Concrete Mathematics
12 | 2 | 500 | Concrete Mathematics
И здесь результат вышеупомянутого запроса:
author_last_name | dewey_number | numoccurrences
------------------+--------------+----------------
Fowler | 600 | 4
Knuth | 600 | 3
Knuth | 500 | 3
Lang | 500 | 2
Проблема в том, что в случае сбоя realloc ()
функция вернет NULL, но исходный блок все равно будет выделен. Однако вы только что перезаписали указатель на этот блок и больше не можете освободить (или использовать) его.
Если realloc () терпит неудачу, она возвращает ноль и исходный блок не освобождается . Эта строка:
Hash->Columns = (HASH_COLUMN *)realloc(Hash->Columns, Hash->nColumns * sizeof(HASH_COLUMN)); // line 243
не проверяет возвращаемое значение. Поэтому, если realloc () не работает, в Hash-> Columns записывается null, и происходит утечка исходного блока.
Не уверен, что это проблема, но это потенциально проблематично. Из справочной страницы для realloc ()
:
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
После успешного завершения с размером, отличным от 0,
realloc ()
возвращает указатель на (возможно, перемещенный ) выделенное пространство. Если размер равен 0, возвращается либо нулевой указатель, либо уникальный указатель, который может быть успешно передан вfree ()
. Если доступной памяти недостаточно,realloc ()
возвращает нулевой указатель и устанавливает для errno значение [ENOMEM].
Что произойдет, если недостаточно места для расширенного объекта, старый объект по-прежнему действителен и не освобожден, но realloc ()
возвращает NULL
. Поэтому вам следует сохранить результат, возвращаемый функцией realloc ()
, в отдельной переменной, проверьте эту переменную на NULL
, и если это не так, присвойте ее Hash-> Columns
.
Ага - комментарий асвейкау:
но если бы это была утечка, которую он видит в valgrind, было бы нулевое разыменование, и он бы рухнул. я предполагаю, что есть некоторый код, который он не предоставляет, но имеет утечку.
привел меня к другой проблеме - структура данных, размер которой вы изменяете, содержит указатели на строки, выделенные с помощью strdup ()
. если ваш вызов realloc ()
уменьшает выделение, вы потеряете эти указатели, не освободив их должным образом. Я считаю, что Асвейкау прав, что это то, на что жалуется valgrind.
привел меня к другой проблеме - структура данных, размер которой вы изменяете, содержит указатели на строки, выделенные с помощью strdup ()
. если ваш вызов realloc ()
уменьшает выделение, вы потеряете эти указатели, не освободив их должным образом. Я считаю, что Асвейкау прав, что это то, на что жалуется valgrind.
привел меня к другой проблеме - структура данных, размер которой вы изменяете, содержит указатели на строки, выделенные с помощью strdup ()
. если ваш вызов realloc ()
уменьшает выделение, вы потеряете эти указатели, не освободив их должным образом. Я считаю, что Асвейкау прав, что это то, на что жалуется valgrind.
Valgrind не говорит, что утечка происходит в строке realloc
- он говорит, что память, выделенная этой строкой realloc
, является память, которая, в конце концов, утекает. Однако Valgrind не знает, где - он просто знает, что у вас больше нет ссылки на эту память, поэтому было бы невозможно освободить
ее. (OP может это знать, но очевидно, что многие из ответчиков этого не знают!)
Короче говоря, код, который вы вставили, не вызывает проблемы (хотя проблема, которую поднимает Майкл Берр, определенно реальна, но поскольку вы даже не проверяете NULL
, возвращенное из realloc
...)
Где-то в вашем коде должно быть свободное (Hash-> Столбцы)
, которого сейчас нет. Найдите это место - вероятно, незадолго до освобождения самого хеша
и добавьте его.
В Mac OS X и FreeBSD et al. у вас также есть функция reallocf ():
man 3 malloc | less -p reallocf
...
The reallocf() function is identical to the realloc() function, except
that it will free the passed pointer when the requested memory cannot be
allocated. This is a FreeBSD specific API designed to ease the problems
with traditional coding styles for realloc causing memory leaks in
libraries.