我需要帮助。我有一个原始 SQL 查询 (MySql),它根据制造商的权重计算我的产品排名。 这两个表可以恢复为:
产品
身份证 | 合作伙伴ID |
---|---|
11 | 1 |
12 | 3 |
13 | 2 |
14 | 3 |
15 | 1 |
合作伙伴
身份证 | 位置 |
---|---|
1 | 2 |
2 | 3 |
3 | 1 |
我的查询是这样的:
INSERT INTO product_rank (product_id,partner_id,weight,`rank`)
SELECT g.product_id, g.partner_id, g.weight, g.rank FROM (SELECT (@rank:=@rank +1) AS rank, m.* FROM
(SELECT x.id AS product_id, x.partner_id, x.weight FROM
(
SELECT
t.id,
t.partner_id,
p.position,
CASE
WHEN @partner_id != t.partner_id THEN @rownum := 0
WHEN @partner_id = t.partner_id THEN @rownum := @rownum + 1
ELSE @rownum
END AS weight,
@partner_id := t.partner_id
FROM product t
JOIN partner p ON t.partner_id = p.id
) x
ORDER BY x.weight, x.position)m )g, (SELECT @rank := 0) r;
如果我直接从 MySQL 控制台运行查询,它会起作用:我的结果为
身份证 | 产品_id | partner_id | 重量 | 排名 |
---|---|---|---|---|
1 | 12 | 3 | 0 | 1 |
2 | 11 | 1 | 0 | 2 |
3 | 13 | 2 | 0 | 3 |
4 | 14 | 3 | 1 | 4 |
5 | 15 | 1 | 1 | 5 |
但是如果我使用 Doctrine 和
$this->getEntityManager()->getConnection()->executeStatement
权重和排名始终设置为零。
我哪里做错了?
您面临的问题可能与 Doctrine 如何处理准备好的语句和 SQL 查询的执行有关。在准备好的语句中,SQL 查询被解析和准备一次,然后绑定参数并使用不同的值多次执行它。但是,在您的情况下,您使用的会话变量(@rank、@partner_id)可以在查询的不同执行之间具有有状态行为。
Doctrine 可能不会像直接在 MySQL 控制台中执行原始 SQL 那样处理会话变量及其状态。要解决此问题,您可以尝试以下几种方法:
1。使用 NativeQuery 执行单语句:
不要使用
executeStatement
,而是尝试使用 Doctrine 的 createNativeQuery 并将整个 SQL 查询作为单个语句执行。这有时可以确保会话变量保持预期的行为。
$sql = "INSERT INTO product_rank (product_id, partner_id, weight, `rank`)
SELECT g.product_id, g.partner_id, g.weight, g.rank FROM (...your SQL query...)";
$nativeQuery = $this->getEntityManager()->createNativeQuery($sql);
$nativeQuery->getResult();
2。手动重置会话变量:
由于会话变量在原始 SQL 执行和 Doctrine 之间的行为可能有所不同,因此您可以考虑在执行查询之前手动重置会话变量。
$this->getEntityManager()->getConnection()->executeStatement("SET @rank := 0;");
// Now execute your main query
$this->getEntityManager()->getConnection()->executeStatement("...your main SQL query...");
尝试这些方法,看看是否能解决问题。请记住,与直接 SQL 控制台执行相比,Doctrine 在处理 SQL 执行的方式上可能存在一些差异,这些解决方法旨在解决这些差异。