TYPO3 DBAL Querybuilder:嵌套 SELECT 语句?
TYPO3 DBAL Querybuilder: Nested SELECT statements?
是否可以使用 DBAL QueryBuilder 构建如下所示的嵌套 SELECT 语句?
SELECT i.id, i.stable_id, i.version, i.title
FROM initiatives AS i
INNER JOIN (
SELECT stable_id, MAX(version) AS max_version FROM initiatives GROUP BY stable_id
) AS tbl1
ON i.stable_id = tbl1.stable_id AND i.version = tbl1.max_version
ORDER BY i.stable_id ASC
目标是查询外部非 TYPO3 table,其中包含每个数据集的不同版本。只应呈现版本号最高的数据集。数据库如下所示:
id, stable_id, version, [其余数据行]
stable_id
是数据集的外部id。 id
是内部自增 id。 version
也会自动递增。
代码示例:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
$result = $queryBuilder
->select(...$this->select)
->from($this->table)
->join(
'initiatives',
$queryBuilder
->select('stable_id, MAX(version) AS max_version' )
->from('initiatives')
->groupBy('stable_id'),
'tbl1',
$queryBuilder->and(
$queryBuilder->expr()->eq(
'initiatives.stable_id',
$queryBuilder->quoteIdentifier('tbl1.stable_id')
),
$queryBuilder->expr()->eq(
'initiatives.version',
$queryBuilder->quoteIdentifier('tbl1.max_version')
)
)
)
->orderBy('stable_id', 'DESC')
我想不出 ON ... AND 语句的正确语法。有什么想法吗?
Extbase 查询具有 JOIN
功能,但在其他方面非常有限。不过,您可以使用自定义 SQL(参见 ->statement()
here)。
构建复杂查询的更好 API 是 (Doctrine DBAL) QueryBuilder, including support for JOINs
, database functions like MAX()
and raw expressions (->addSelectLiteral()
). Make sure to read until the ExpressionBuilder 它变得有趣的地方。
所以 Extbase 查询对于检索 Extbase(模型)对象很有用。它可以隐含地使用它对您的数据结构的了解,以便为您节省一些代码,但只支持相当简单的查询。
(Doctrine DBAL) QueryBuilder 满足所有其他需求。如果需要,您也可以将原始数据转换为 Extbase 模型。 (for example $propertyMapper->convert($data, Job::class)
).
我意识到我们对两者缺乏明确的区分,因为它们在某个时候都被称为“QueryBuilder”,但它们是完全不同的。这就是为什么我喜欢在提到非 Extbase 时添加“Doctrine”。
具有 JOIN ON
多个条件的示例。
$q = TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(TYPO3\CMS\Core\Database\ConnectionPool::class)
->getQueryBuilderForTable('fe_users');
$res = $q->select('*')
->from('tt_content', 'c')
->join(
'c',
'be_users',
'bu',
$q->expr()->andX(
$q->expr()->eq(
'c.cruser_id', $q->quoteIdentifier('bu.uid')
),
$q->expr()->comparison(
'2', '=', '2'
)
)
)
->setMaxResults(5)
->execute()
->fetchAllAssociative();
简短回答:这是不可能的,因为要加入的 table 是动态生成的。相关表达式被反引号,因此导致 SQL 错误。
但是:SQL 查询可以更改为下面的 SQL 查询,其功能基本相同:
SELECT i1.id,stable_id, version, title, p.name, l.name, s.name
FROM initiatives i1
WHERE version = (
SELECT MAX(i2.version)
FROM initiatives i2
WHERE i1.stable_id = i2.stable_id
)
ORDER BY stable_id ASC
这可以用 DBAL queryBuilder 重建:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
$result = $queryBuilder
->select(...$this->select)
->from($this->table)
->where(
$queryBuilder->expr()->eq(
'initiatives.version',
'(SELECT MAX(i2.version) FROM initiatives i2 WHERE initiatives.stable_id = i2.stable_id)'
),
->orderBy('stable_id', 'DESC')
->setMaxResults( 50 )
->execute();
是否可以使用 DBAL QueryBuilder 构建如下所示的嵌套 SELECT 语句?
SELECT i.id, i.stable_id, i.version, i.title
FROM initiatives AS i
INNER JOIN (
SELECT stable_id, MAX(version) AS max_version FROM initiatives GROUP BY stable_id
) AS tbl1
ON i.stable_id = tbl1.stable_id AND i.version = tbl1.max_version
ORDER BY i.stable_id ASC
目标是查询外部非 TYPO3 table,其中包含每个数据集的不同版本。只应呈现版本号最高的数据集。数据库如下所示:
id, stable_id, version, [其余数据行]
stable_id
是数据集的外部id。 id
是内部自增 id。 version
也会自动递增。
代码示例:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
$result = $queryBuilder
->select(...$this->select)
->from($this->table)
->join(
'initiatives',
$queryBuilder
->select('stable_id, MAX(version) AS max_version' )
->from('initiatives')
->groupBy('stable_id'),
'tbl1',
$queryBuilder->and(
$queryBuilder->expr()->eq(
'initiatives.stable_id',
$queryBuilder->quoteIdentifier('tbl1.stable_id')
),
$queryBuilder->expr()->eq(
'initiatives.version',
$queryBuilder->quoteIdentifier('tbl1.max_version')
)
)
)
->orderBy('stable_id', 'DESC')
我想不出 ON ... AND 语句的正确语法。有什么想法吗?
Extbase 查询具有 JOIN
功能,但在其他方面非常有限。不过,您可以使用自定义 SQL(参见 ->statement()
here)。
构建复杂查询的更好 API 是 (Doctrine DBAL) QueryBuilder, including support for JOINs
, database functions like MAX()
and raw expressions (->addSelectLiteral()
). Make sure to read until the ExpressionBuilder 它变得有趣的地方。
所以 Extbase 查询对于检索 Extbase(模型)对象很有用。它可以隐含地使用它对您的数据结构的了解,以便为您节省一些代码,但只支持相当简单的查询。
(Doctrine DBAL) QueryBuilder 满足所有其他需求。如果需要,您也可以将原始数据转换为 Extbase 模型。 (for example $propertyMapper->convert($data, Job::class)
).
我意识到我们对两者缺乏明确的区分,因为它们在某个时候都被称为“QueryBuilder”,但它们是完全不同的。这就是为什么我喜欢在提到非 Extbase 时添加“Doctrine”。
具有 JOIN ON
多个条件的示例。
$q = TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(TYPO3\CMS\Core\Database\ConnectionPool::class)
->getQueryBuilderForTable('fe_users');
$res = $q->select('*')
->from('tt_content', 'c')
->join(
'c',
'be_users',
'bu',
$q->expr()->andX(
$q->expr()->eq(
'c.cruser_id', $q->quoteIdentifier('bu.uid')
),
$q->expr()->comparison(
'2', '=', '2'
)
)
)
->setMaxResults(5)
->execute()
->fetchAllAssociative();
简短回答:这是不可能的,因为要加入的 table 是动态生成的。相关表达式被反引号,因此导致 SQL 错误。
但是:SQL 查询可以更改为下面的 SQL 查询,其功能基本相同:
SELECT i1.id,stable_id, version, title, p.name, l.name, s.name
FROM initiatives i1
WHERE version = (
SELECT MAX(i2.version)
FROM initiatives i2
WHERE i1.stable_id = i2.stable_id
)
ORDER BY stable_id ASC
这可以用 DBAL queryBuilder 重建:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
$result = $queryBuilder
->select(...$this->select)
->from($this->table)
->where(
$queryBuilder->expr()->eq(
'initiatives.version',
'(SELECT MAX(i2.version) FROM initiatives i2 WHERE initiatives.stable_id = i2.stable_id)'
),
->orderBy('stable_id', 'DESC')
->setMaxResults( 50 )
->execute();