Переместите ваше объявление (или полное определение) из shouldBeBefore
выше main
, где вы вызываете heapify
. Но когда вы вызываете heapify
, вы просто передаете имя функции. heapify
вызовет вашу функцию shouldBeBefore
со своими собственными параметрами.
void heapify(S bt[], unsigned els, bool(*shouldBeBefore)(const S & a, const S & b));
bool shouldBeBefore(const S & a, const S & b);
int main()
{
S test[9] = { {1.1,1,'A'},{1.3,2,'B'},{1.8,3,'C'},{1.7,4,'D'},{5.1,5,'E'},
{4.3,6,'F'},{3.8,7,'G'},{4.7,8,'H'},{2.7,9,'I'} };
unsigned int length = sizeof(test)/sizeof(test[0]); // 9
heapify(S, length, shouldBeBefore);
return 0;
}
bool shouldBeBefore(const S & a, const S & b)
{
return (a.x < b.x);
}
В вашей реализации heapify
вы можете вызывать shouldBeBefore
, как и любую другую функцию:
void heapify(S bt[], unsigned els, bool(*shouldBeBefore)(const S & a, const S & b))
{
...
if (shouldBeBefore(S[i+1], S[i]) {
...
}
...
}
Что-то подобное? Соедините вашу таблицу с самим собой и исключите строки, для которых был найден более высокий сигнал.
select cur.id, cur.signal, cur.station, cur.ownerid
from yourtable cur
where not exists (
select *
from yourtable high
where high.id = cur.id
and high.signal > cur.signal
)
В этом списке будет указана одна строка для каждого самого высокого сигнала, поэтому может быть несколько строк на идентификатор.
Вы выполняете групповую максимальную / минимальную операцию. Это обычная ловушка: кажется, что это должно быть легко сделать, но в SQL это усугубляется.
Существует несколько подходов (как стандартных ANSI, так и специфичных для поставщиков) к этой проблеме, большинство которые неоптимальны во многих ситуациях. Некоторые выдадут вам несколько строк, если несколько строк имеют одинаковое максимальное / минимальное значение; некоторые не будут. Некоторые хорошо работают на столах с небольшим количеством групп; другие более эффективны для большего числа групп с меньшим количеством строк в группе.
Вот обсуждение некоторых из них (MySQL-смещено, но обычно применимо). Лично, если я знаю, что нет множественных максимумов (или мне все равно, как их получить), я часто склоняюсь к методу null-left-self-join, который я опубликую как никто другой:
SELECT reading.ID, reading.Signal, reading.Station, reading.OwnerID
FROM readings AS reading
LEFT JOIN readings AS highersignal
ON highersignal.ID=reading.ID AND highersignal.Signal>reading.Signal
WHERE highersignal.ID IS NULL;
В классическом SQL-92 (без использования операций OLAP, используемых Quassnoi) вы можете использовать:
SELECT g.ID, g.MaxSignal, t.Station, t.OwnerID
FROM (SELECT id, MAX(Signal) AS MaxSignal
FROM t
GROUP BY id) AS g
JOIN t ON g.id = t.id AND g.MaxSignal = t.Signal;
(Непроверенный синтаксис; предполагается, что ваша таблица имеет значение «t».)
Подзапрос в FROM предложение определяет максимальное значение сигнала для каждого идентификатора; объединение объединяет это с соответствующей строкой данных из основной таблицы.
NB: если есть несколько записей для определенного идентификатора, которые имеют одинаковый уровень сигнала и этот уровень равен MAX (), то вы получите несколько выходных строк для этого идентификатора.
Протестировано на IBM Informix Dynamic Server 11.50.FC3, работающем в Solaris 10:
+ CREATE TEMP TABLE signal_info
(
id INTEGER NOT NULL,
signal INTEGER NOT NULL,
station CHAR(5) NOT NULL,
ownerid INTEGER NOT NULL
);
+ INSERT INTO signal_info VALUES(111, -120, 'Home', 1);
+ INSERT INTO signal_info VALUES(111, -130, 'Car' , 1);
+ INSERT INTO signal_info VALUES(111, -135, 'Work', 2);
+ INSERT INTO signal_info VALUES(222, -98 , 'Home', 2);
+ INSERT INTO signal_info VALUES(222, -95 , 'Work', 1);
+ INSERT INTO signal_info VALUES(222, -103, 'Work', 2);
+ SELECT g.ID, g.MaxSignal, t.Station, t.OwnerID
FROM (SELECT id, MAX(Signal) AS MaxSignal
FROM signal_info
GROUP BY id) AS g
JOIN signal_info AS t ON g.id = t.id AND g.MaxSignal = t.Signal;
111 -120 Home 1
222 -95 Work 1
Я назвал таблицу Signal_Info для этого теста - но, похоже, она дает правильный ответ. Это только показывает, что есть по крайней мере, одна СУБД, поддерживающая нотацию. Однако я немного удивлен, что MS SQL Server не поддерживает - какую версию вы используете?
Меня никогда не перестает удивлять, как часто вопросы SQL отправляются без имен таблиц.
select a.id, b.signal, a.station, a.owner from
mytable a
join
(SELECT ID, MAX(Signal) as Signal FROM mytable GROUP BY ID) b
on a.id = b.id AND a.Signal = b.Signal
WITH q AS
(
SELECT c.*, ROW_NUMBER() OVER (PARTITION BY id ORDER BY signal DESC) rn
FROM mytable
)
SELECT *
FROM q
WHERE rn = 1
Это вернет одну строку, даже если есть дубликаты MAX (сигнал)
для данного ID
.
Наличие индекса (id, signal)
значительно улучшит этот запрос.