Так или иначе, делается это очень просто:
Для начала, необходимо сделать массив $header будущей таблицы:
$header = array(
array('data' => 'Видимое имя поля', 'field' => 'field in db'),
);
Теперь надо получить настройки базы данных, используемой Drupal 7 по умолчанию, берутся они из суперглобальной переменной $databases:
global $databases;
$current_base = $databases['default']['default'];
$mysqli = new mysqli($current_base['host'],$current_base['username'],$current_base['password'],$current_base['database']);
Далее необходимо установить кодировку UTF-8 по-умолчанию:
$mysqli->set_charset("utf8");
А дальше выполняем непосредственно сам запрос, при этом предполагается, что в $query находится корректный SQL-запрос:
$result = $mysqli->query($query);
Далее, обходим все записи и строим массив строк:
while ($record = $result->fetch_object()) {
$rows[] = array(
$record->title,
);
}
А далее просто рендерим получившуюся таблицу и выводим
$output = theme('table', array('header' => $header, 'rows' => $rows));
return $output;
В результате этих нехитрых действий получаем таблицу, в которую выведен наш запрос и заголовок которой автоматически сгененрирован для передачи методом GET параметров сортировки таблицы. Теперь надо только обработать полученные данные, например, следующим образом:
Для удобства был создан костыль, содержащий запись "имя поля" - "имя поля в БД", так как в GET друпалом передаётся название поля в точности, как оно отображается для пользователя:
$map = array (
'Видимое имя поля' => 'field in bd',
);
А далее просто обрабатывал массив $_GET и добавлял к строке $query сортировку по полю, возрастающую или убывающую:
if (isset($_GET['sort'])) {
$query.=" ORDER BY ".$map[$_GET['order']]." ";
$_GET['sort'] == 'asc' ? $query.="ASC" : $query.="DESC";
}