无法创建用于将原始 SQL 查询解析到单个数据库 table 的 Doctrine ResultSetMapping
Trouble creating a Doctrine ResultSetMapping for parsing a raw SQL query to a single database table
我正在尝试将原始 SQL 命令转换为 Doctrine 实体。 sql命令是:
$sql = 'SELECT SUM(IF (SCORE = 1, 1, 0)) AS UPVOTE, SUM(IF (SCORE = -1, 1, 0)) AS DOWNVOTE, BLOCKID, ELEMENTID FROM Voting GROUP BY BLOCKID, ELEMENTID';
有效 returns 来自投票 table:
UPVOTE DOWNVOTE BLOCKID ELEMENTID
1 1 3223 person1
3 2 3223 person2
0 1 3223 person3
我的控制器文件中有以下 PHP 代码,它当前返回一个空数组:
$sql = 'SELECT SUM(IF (SCORE = 1, 1, 0)) AS UPVOTE, SUM(IF (SCORE = -1, 1, 0)) AS DOWNVOTE, BLOCKID, ELEMENTID FROM Voting GROUP BY BLOCKID, ELEMENTID';
$rsm = new ResultSetMapping();
$rsm->addEntityResult('Concrete\Entity\Vote', 'u');
$rsm->addFieldResult('u', 'blockid', 'blockid');
$rsm->addFieldResult('u', 'elementId', 'elementId');
$rsm->addFieldResult('u', 'score', 'score');
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'ipAddress', 'ipAddress');
$rsm->addFieldResult('u', 'created_at', 'created_at');
$rsm->addScalarResult('upvote', 'upvote');
$rsm->addScalarResult('downvote', 'downvote');
$query = $this->em->createNativeQuery($sql, $rsm);
$results = $query->getResult();
echo json_encode($results);
我已尝试查阅 Doctrine 文档,但无法确定我的问题所在。我已经在我的 table 中的所有列(例如 id、ipAddress、created_at)上调用了 addFieldResult,这些列根本没有出现在结果中 - 这是否必需?
使用上面的代码我没有得到任何错误,只是返回了一个空数组。我是漏掉了什么还是只是做错了?
您不需要使用本机查询来执行这种查询。你可以靠 CASE
expressions 来写你的条件。使用查询构建器,您的查询将如下所示:
$results = $entityManager->createQueryBuilder()
->from('Concrete\Entity\Vote', 'v')
->select('v.elementId', 'v.blockId')
->addSelect('SUM(CASE WHEN v.score = 1 THEN 1 ELSE 0 END) AS upvote')
->addSelect('SUM(CASE WHEN v.score = -1 THEN 1 ELSE 0 END) AS downvote')
->groupBy('v.blockId')
->addGroupBy('v.elementId')
->getQuery()
->getResult();
如果您仍想使用本机查询,如果您只是想从中检索 BLOCKID
和 ELEMENTID
,则无需过度使用 ResultSetMapping
你的table。只需使用 addScalarResult
,第一个参数是出现在 SELECT
子句中的 field/alias 的名称,第二个参数是您希望它在结果集中具有的别名。 (您也可以添加第三个参数来指定要检索的标量值的类型,请参阅下面的 block_id
或 upvote
)。
有一个像这样的 Vote
实体:
/** @ORM\Table(name="votes") */
class Vote
{
/**
* @ORM\Column(name="id", type="integer", unique=true)
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/** @ORM\Column(name="block_id", type="integer") */
private $blockId;
/** @ORM\Column(name="element_id", type="string") */
private $elementId;
/** @ORM\Column(name="score", type="integer") */
private $score;
}
以下本机查询将输出与使用上述查询构建器构建的查询相同的结果。
$sql = 'SELECT SUM(IF (SCORE = 1, 1, 0)) AS upvote, SUM(IF (SCORE = -1, 1, 0)) AS downvote, block_id, element_id FROM votes GROUP BY block_id, element_id';
$rsm = new ResultSetMapping();
$rsm->addScalarResult('block_id', 'blockId', 'integer');
$rsm->addScalarResult('element_id', 'elementId');
$rsm->addScalarResult('upvote', 'upvote', 'integer');
$rsm->addScalarResult('downvote', 'downvote', 'integer');
$query = $em->createNativeQuery($sql, $rsm);
$result = $query->getResult();
您将获得的唯一区别是 upvote
/downvote
值将是整数而不是字符串,因为您可以在此处指定它(虽然您不能使用查询构建器)。
我正在尝试将原始 SQL 命令转换为 Doctrine 实体。 sql命令是:
$sql = 'SELECT SUM(IF (SCORE = 1, 1, 0)) AS UPVOTE, SUM(IF (SCORE = -1, 1, 0)) AS DOWNVOTE, BLOCKID, ELEMENTID FROM Voting GROUP BY BLOCKID, ELEMENTID';
有效 returns 来自投票 table:
UPVOTE DOWNVOTE BLOCKID ELEMENTID
1 1 3223 person1
3 2 3223 person2
0 1 3223 person3
我的控制器文件中有以下 PHP 代码,它当前返回一个空数组:
$sql = 'SELECT SUM(IF (SCORE = 1, 1, 0)) AS UPVOTE, SUM(IF (SCORE = -1, 1, 0)) AS DOWNVOTE, BLOCKID, ELEMENTID FROM Voting GROUP BY BLOCKID, ELEMENTID';
$rsm = new ResultSetMapping();
$rsm->addEntityResult('Concrete\Entity\Vote', 'u');
$rsm->addFieldResult('u', 'blockid', 'blockid');
$rsm->addFieldResult('u', 'elementId', 'elementId');
$rsm->addFieldResult('u', 'score', 'score');
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'ipAddress', 'ipAddress');
$rsm->addFieldResult('u', 'created_at', 'created_at');
$rsm->addScalarResult('upvote', 'upvote');
$rsm->addScalarResult('downvote', 'downvote');
$query = $this->em->createNativeQuery($sql, $rsm);
$results = $query->getResult();
echo json_encode($results);
我已尝试查阅 Doctrine 文档,但无法确定我的问题所在。我已经在我的 table 中的所有列(例如 id、ipAddress、created_at)上调用了 addFieldResult,这些列根本没有出现在结果中 - 这是否必需?
使用上面的代码我没有得到任何错误,只是返回了一个空数组。我是漏掉了什么还是只是做错了?
您不需要使用本机查询来执行这种查询。你可以靠 CASE
expressions 来写你的条件。使用查询构建器,您的查询将如下所示:
$results = $entityManager->createQueryBuilder()
->from('Concrete\Entity\Vote', 'v')
->select('v.elementId', 'v.blockId')
->addSelect('SUM(CASE WHEN v.score = 1 THEN 1 ELSE 0 END) AS upvote')
->addSelect('SUM(CASE WHEN v.score = -1 THEN 1 ELSE 0 END) AS downvote')
->groupBy('v.blockId')
->addGroupBy('v.elementId')
->getQuery()
->getResult();
如果您仍想使用本机查询,如果您只是想从中检索 BLOCKID
和 ELEMENTID
,则无需过度使用 ResultSetMapping
你的table。只需使用 addScalarResult
,第一个参数是出现在 SELECT
子句中的 field/alias 的名称,第二个参数是您希望它在结果集中具有的别名。 (您也可以添加第三个参数来指定要检索的标量值的类型,请参阅下面的 block_id
或 upvote
)。
有一个像这样的 Vote
实体:
/** @ORM\Table(name="votes") */
class Vote
{
/**
* @ORM\Column(name="id", type="integer", unique=true)
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/** @ORM\Column(name="block_id", type="integer") */
private $blockId;
/** @ORM\Column(name="element_id", type="string") */
private $elementId;
/** @ORM\Column(name="score", type="integer") */
private $score;
}
以下本机查询将输出与使用上述查询构建器构建的查询相同的结果。
$sql = 'SELECT SUM(IF (SCORE = 1, 1, 0)) AS upvote, SUM(IF (SCORE = -1, 1, 0)) AS downvote, block_id, element_id FROM votes GROUP BY block_id, element_id';
$rsm = new ResultSetMapping();
$rsm->addScalarResult('block_id', 'blockId', 'integer');
$rsm->addScalarResult('element_id', 'elementId');
$rsm->addScalarResult('upvote', 'upvote', 'integer');
$rsm->addScalarResult('downvote', 'downvote', 'integer');
$query = $em->createNativeQuery($sql, $rsm);
$result = $query->getResult();
您将获得的唯一区别是 upvote
/downvote
值将是整数而不是字符串,因为您可以在此处指定它(虽然您不能使用查询构建器)。