这是一个非常明显的数据问题,但是我在任何地方都找不到简单的解决方案。
使用TYPO3 QueryBuilder,如何从每个用户具有多个条目的表中为每个用户选择最新条目?
uid user_id value crdate
1 1 0 123456
2 1 1 123400
3 2 1 123356
4 2 0 123300
我尝试了许多原始SQL方法,并最终基于此解决方案找到了一种可行的方法- How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
SELECT *
FROM `tx_tablename` AS `tt`
INNER JOIN (
SELECT `uid`, `user_id`, MAX(`crdate`) AS `MaxDateTime`
FROM `tx_tablename`
GROUP BY `user_id`
) AS `groupedtt`
ON `tt`.`user_id` = `groupedtt`.`user_id`
AND `tt`.`crdate` = `groupedtt`.`MaxDateTime`
WHERE `tt`.`consent_content` = 3
但我看不到如何在QueryBuilder中重现此内容,因为-> join()语句仅接受表名作为参数,而不接受SQL,并且-> join()仅接受一个连接条件,而不接受两个。
是否还有其他人找到了可以在QueryBuilder中使用的解决方案? 非常感谢
答案 0 :(得分:1)
引用是在TYPO3 QueryBuilder中完成的。您可以直接使用ConcreteQueryBuilder绕过它。
但是,您必须自己引用标识符,否则将引发异常。
这应该可以解决您的伪代码:
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
...
$subQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_tablename');
$subQuery = $subQueryBuilder
->select('uid', 'user_id')
->from('tx_tablename')
->addSelectLiteral(
$subQueryBuilder->expr()->max('crdate', 'max_crdate')
)
->groupBy('user_id');
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_tablename');
$queryResult = $queryBuilder
->select('a.*')
->from('tx_tablename', 'a')
;
$queryBuilder
->getConcreteQueryBuilder()
->innerJoin(
$queryBuilder->quoteIdentifier('a'), // !!! important, quote identifier yourself
'(' . $subQuery->getSQL() . ')',
$queryBuilder->quoteIdentifier('b'), // !!! important, quote identifier yourself
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('a.user_id', $queryBuilder->quoteIdentifier('b.user_id')),
$queryBuilder->expr()->eq('a.crdate', $queryBuilder->quoteIdentifier('b.max_crdate'))
) // andX()
) // innerJoin()
;
$queryResult = $queryBuilder->execute();
修改1
固定的代码示例。需要quoteIdentifier()
而不是createNamedParam()
。
注意
如果您使用嵌套的selects / subselects AND并使用命名参数,则必须使用最外面的queryBuilder实例来创建命名参数,而不是当前级别的queryBuilder。
答案 1 :(得分:0)
您可能需要一个子查询。请尝试以下操作。
Enter your name: Deepak
Hello Deepak
How are you feeling today? Are you doing Good or Bad? Good
Ok Deepak So today you are basically feeling Good.
但是,现在的代码会在use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
...
$subQueryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_tablename');
$subQuery = $subQueryBuilder
->select('uid', 'user_id')
->from('tx_tablename')
->addSelectLiteral(
$subQueryBuilder->expr()->max('crdate', 'max_crdate')
)
->groupBy('user_id');
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_tablename');
$queryResult = $queryBuilder
->select('a.*')
->from('tx_tablename', 'a')
->innerJoin(
'a',
'(' . $subQuery->getSQL() . ')',
'b',
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('a.user_id', $queryBuilder->createNamedParameter('b.user_id', \PDO::PARAM_STR)),
$queryBuilder->expr()->eq('a.crdate', $queryBuilder->createNamedParameter('b.max_crdate', \PDO::PARAM_STR))
)
)
->execute();
查询内部产生双反引号(`) 。我不确定如何摆脱它们,但是代码显示了这一概念。
答案 2 :(得分:0)
您是对的-您不能在TYPO3的join()
,innerJoin()
,leftJoin()
和rightJoin()
中将子查询用作参数,因为使用{ {1}}(请参见GitHub的TYPO3 v10.2源代码)并添加了反引号。
我想知道以下SQL查询是否返回您所追求的结果:
quoteIdentifier()
在这种情况下,Doctrine代码将如下所示:
SELECT `uid`, `user_id`, value, MAX(`crdate`)
FROM `tx_tablename`
GROUP BY `user_id`
HAVING MAX(`crdate`);