Способ создания подзапроса с использованием JDatabase

В http://docs.joomla.org/Selecting_data_using_JDatabase нет документального метода для записи подзапроса с использованием JDatabase.

https://gist.github.com/gunjanpatel/8663333 иллюстрирует один из способов достижения этого (несколько бит опущен):

$subQuery = $db->getQuery(true);
$query    = $db->getQuery(true);

// Create the base subQuery select statement.
$subQuery->select('*')
    ->from($db->quoteName('#__sub_table'))
    ->where($db->quoteName('subTest') . ' = ' . $db->quote('1'));

// Create the base select statement.
$query->select('*')
    ->from($db->quoteName('#__table'))
    ->where($db->quoteName('state') . ' = ' . $db->quote('1'))
    ->where($db->quoteName('subCheckIn') . ' IN (' . $subQuery->__toString() . ')')
    ->order($db->quoteName('ordering') . ' ASC');

// Set the query and load the result.
$db->setQuery($query);

Это похоже на хороший, правдоподобный подход, но есть ли лучший?

29 голосов | спросил betweenbrain 22 PMpTue, 22 Apr 2014 21:35:44 +040035Tuesday 2014, 21:35:44

3 ответа


15

Да, насколько мне известно, способ, которым вы создали подзапрос, - это тот, который был принят большинством разработчиков расширений joomla.

Я использую тот же самый метод для некоторых моих расширений и пользовательских расширений, созданных для клиентов.

Нет никакого «официального» способа сделать это, но делать это, как вы показали, позволяет использовать построитель запросов и по-прежнему сохранять хорошую читаемость.

ответил Skullbock 23 AMpWed, 23 Apr 2014 11:18:16 +040018Wednesday 2014, 11:18:16
10

AFAIK не имеет встроенного способа сделать легкие подзапросы, что, вероятно, является недостатком в системе и должно быть исправлено с помощью PR.

Однако я не вижу проблемы с вашим примером - кажется достаточно разумным.

~~~

Вот пример в ответ на комментарий @ DavidFritsch ниже. Чем больше я думаю об этом, тем лучше мне нравится более простой подход, отображаемый в OP. Более ясно, что происходит.

$query = $this->db->getQuery(true)
  ->select('a.*')
  ->subQuery()
    ->select('b.*')
    ->from('#__table_b AS b')
    ->as('subQueryResult')
  ->endSubQuery()
  ->from('#__table_a AS a');
ответил Don Gilbert 22 PMpTue, 22 Apr 2014 23:34:44 +040034Tuesday 2014, 23:34:44
3

Существует также способ выполнения запросов, содержащих подзапросы с использованием API платформы Joomla. Основная идея использования подзапросов основана на gunjanpatel .

Вот пример выполнения запросов на вложенных моделях моделей

SQL-запрос:

-- Find the Immediate Subordinates of a Node
SELECT node.title, (COUNT(parent.id) - (sub_tree.depth + 1)) AS depth
FROM lubd3_usergroups AS node,
        lubd3_usergroups AS parent,
        lubd3_usergroups AS sub_parent,
        (
                SELECT node.id, (COUNT(parent.id) - 1) AS depth
                FROM lubd3_usergroups AS node,
                        lubd3_usergroups AS parent
                WHERE node.lft BETWEEN parent.lft AND parent.rgt
                        AND node.id = 1
                GROUP BY node.id
                ORDER BY node.lft
        )AS sub_tree
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
        AND sub_parent.id = sub_tree.id
GROUP BY node.id
-- not showing the parent node
HAVING depth = 1
-- showing the parent node
-- HAVING depth <= 1
ORDER BY node.lft;

и преобразованный запрос, который должен быть выполнен Joomla:

// Create the subQuery select statement.
// Nested Set Queries: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
// CROSS JOIN: http://www.informit.com/articles/article.aspx?p=30875&seqNum=5
$subQuery->select(array('node.id', '(COUNT(parent.id) - 1) AS depth'))
    ->from($db->quoteName('#__usergroups') . 'node')
    ->join('CROSS', $db->quoteName('#__usergroups', 'parent'))
    ->where($db->quoteName('node.lft') . ' BETWEEN  ' . $db->quoteName('parent.lft') . ' AND ' . $db->quoteName('parent.rgt') . ' AND ' . $db->quoteName('node.id') . ' = ' . $db->quote('1'))
    ->group($db->quoteName('node.id'))
    ->order($db->quoteName('node.lft'));

// Create the base select statement.
$query->select(array('node.title', '(COUNT(parent.id) - (sub_tree.depth + 1)) AS depth'))
    ->from($db->quoteName('#__usergroups') . 'node')
    ->join('CROSS', $db->quoteName('#__usergroups', 'parent'))
    ->join('CROSS', $db->quoteName('#__usergroups', 'sub_parent'))
    ->join('CROSS', '(' . $subQuery .') AS sub_tree')
    ->where($db->quoteName('node.lft') . ' BETWEEN  ' . $db->quoteName('parent.lft') . ' AND ' . $db->quoteName('parent.rgt')
    . ' AND ' . $db->quoteName('node.lft') . ' BETWEEN  ' . $db->quoteName('sub_parent.lft') . ' AND ' . $db->quoteName('sub_parent.rgt')
    . ' AND ' . $db->quoteName('sub_parent.id') . ' = ' . $db->quoteName('sub_tree.id'))
    ->group($db->quoteName('node.id'))
    ->having($db->quoteName('depth') . ' = ' . $db->quote('1'))
    ->order($db->quoteName('node.lft'));

// Set the query and load the result.
$db->setQuery($query);
$rowList = $db->loadAssocList();

echo "<pre>";
print_r($rowList);
echo "</pre>";
ответил Mario Neubauer 1 stEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 01 Sep 2015 11:30:17 +0300 2015, 11:30:17

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132