TYPO3 DBAL Querybuilder:嵌套的 SELECT 语句?
Posted
技术标签:
【中文标题】TYPO3 DBAL Querybuilder:嵌套的 SELECT 语句?【英文标题】:TYPO3 DBAL Querybuilder: Nested SELECT statements? 【发布时间】:2021-05-19 11:20:40 【问题描述】:是否可以使用 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 表。仅应呈现具有最高版本号的数据集。数据库如下所示:
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 语句的正确语法。有什么想法吗?
【问题讨论】:
【参考方案1】:简短回答:这是不可能的,因为要加入的表是动态生成的。相关表达式被反引号,从而导致 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();
【讨论】:
【参考方案2】:Extbase 查询具有JOIN
功能,但在其他方面非常有限。不过,您可以使用自定义 SQL(请参阅 ->statement()
here)。
构建复杂查询的更好 API 是 (Doctrine DBAL) QueryBuilder,包括对 JOINs
、MAX()
等数据库函数和原始表达式 (->addSelectLiteral()
) 的支持。请务必阅读直到有趣的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();
【讨论】:
对不起,我的错。我实际上想使用 DBAL 查询生成器。我也尝试过使用属性映射,但由于外部表的数据结构不符合 TYPO3 标准而无法成功。 我使用 DBAL 表达式生成器添加了一个无效的代码示例。 运行代码时遇到什么错误?Call to undefined method
。我尝试了不同的语法:$queryBuilder->and()、$queryBuilder->logicalAnd()、$queryBuilder->expr()->and()、$queryBuilder->expr()->logicalAnd(),但没有成功.查看源代码似乎表明JOIN .... ON ( ... AND ...)
语句不可能通过 DBAL 查询构建器。对吗?
是的,这是可能的。 ` ->join( 'c', 'be_users', 'bu', $q->expr()->andX( $q->expr()->eq( 'c.cruser_id', $q->quoteIdentifier ('bu.uid')), $q->expr()->comparison('2', '=', '2')))`以上是关于TYPO3 DBAL Querybuilder:嵌套的 SELECT 语句?的主要内容,如果未能解决你的问题,请参考以下文章
在 Doctrine DBAL 中重用 QueryBuilder
TYPO3 QueryBuilder - 如何查找用户的最新记录?
TYPO3:使用 TYPO3 Querybuilder 在 OrderBy 中使用 IS NULL 和 COALESCE