Простой запрос для Захвата Значения Max для каждого идентификатора

Переместите ваше объявление (или полное определение) из 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]) {
            ...
        }
    ...
}
19
задан Bill Karwin 13 December 2009 в 00:25
поделиться

5 ответов

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

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
)

В этом списке будет указана одна строка для каждого самого высокого сигнала, поэтому может быть несколько строк на идентификатор.

20
ответ дан 30 November 2019 в 03:08
поделиться

Вы выполняете групповую максимальную / минимальную операцию. Это обычная ловушка: кажется, что это должно быть легко сделать, но в 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;
15
ответ дан 30 November 2019 в 03:08
поделиться

В классическом 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 отправляются без имен таблиц.

4
ответ дан 30 November 2019 в 03:08
поделиться
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 
0
ответ дан 30 November 2019 в 03:08
поделиться
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) значительно улучшит этот запрос.

1
ответ дан 30 November 2019 в 03:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: