在 CakePHP3 查询中使用 MySQL 用户定义的变量 select
Using MySQL user-defined variables with CakePHP3 query select
这是我需要的 an example 个:
SELECT
@earnings := (`house_rent`+`conveyance`+`medical`+`dearness`+`others_allowances`) AS earnings ,
@deductions := (`income_tax`+`pro_tax`+`emp_state_insu`+`absence_fine`+`others_deductions`) AS deductions,
@earnings - @deductions AS net_salary
FROM
salary
在我的例子中,我需要一个 SUM(Table.total)
作为单独的 salesTotal
列返回,并在 @salesTotal/@salesQuantity
.
中重复使用
这是我尝试过的:
1.
$query->select([
$query->newExpr([
'@salesTotal := ',
$query->func()->sum('Table.total')
]),
]);
这会生成 @salesTotal := AND SUM(Table.total)
2.
$query->select([
$query->newExpr([
'@salesTotal := ' . $query->func()->sum('Table.total')
]),
]);
结果 警告 (4096):class Cake\Database\Expression\FunctionExpression 的对象无法转换为字符串
3.
$query->select([
$query->newExpr([
'@salesTotal := SUM(Table.total)'
]),
]);
正在收到 警告 (2):array_combine(): Both parameters should have an equal number of elements CORE/src/ORM/ResultSet.php, line 527. It's 。
灵感来自 this answer, the idea was to have the variables declared, and then reused for calculating some other value. This approach could be valuable especially with complex calculations. I used \Cake\ORM\Query::newExpr()
with an edited conjunction。
此外,根据 the MySQL doc on user-defined variables,我试着 SET
提前。
In addition, the default result type of a variable is based on its type at the beginning of the statement. This may have unintended effects if a variable holds a value of one type at the beginning of a statement in which it is also assigned a new value of a different type.
To avoid problems with this behavior, either do not assign a value to and read the value of the same variable within a single statement, or else set the variable to 0, 0.0, or '' to define its type before you use it.
这是我得到的查询:
$connection = $this->{'Example/Table'}->getConnection();
$connection->execute('SET @varSalesTotal = 0.0;');
$connection->execute('SET @varSalesQuantity = 0;');
$query = $this->{'Example/Table'}->find('all', [
// ...
]);
$query->select([
// calculate the @varSalesTotal variable
// SQL: @varSalesTotal := SUM(ExampleTable.total)
'varSalesTotalCol' => $query->newExpr([
'@varSalesTotal',
$query->func()->sum('ExampleTable.total'),
])->setConjunction(':='),
// calculate the @varSalesQuantity variable
// SQL: @varSalesQuantity := SUM(ExampleTable.quantity)
'varSalesQuantityCol' => $query->newExpr([
'@varSalesQuantity',
$query->func()->sum('ExampleTable.quantity'),
])->setConjunction(':='),
// attempt to calculate another value reusing the variables
// SQL: @varSalesTotal/@varSalesQuantity AS calcPriceVar
'calcPriceVar' => $query->newExpr([
'@varSalesTotal',
'@varSalesQuantity',
])->setConjunction('/'),
]);
注意:varSalesTotalCol
和 varSalesQuantityCol
键是必需的,否则我会得到
Warning (2): array_combine(): Both parameters should have an equal number of elements [CORE/src/ORM/ResultSet.php, line 527]
Warning (4096): Argument 1 passed to Cake\ORM\Entity::__construct() must be of the type array, boolean given, called in vendor/cakephp/cakephp/src/ORM/ResultSet.php on line 601 and defined [CORE/src/ORM/Entity.php, line 48]
最终结果,calcPriceVar
为空,显然这没有用。可能是因为:
The order of evaluation for expressions involving user variables is undefined. For example, there is no guarantee that SELECT @a, @a:=@a+1 evaluates @a first and then performs the assignment.
我仍在发布这个,因为我找不到任何使用 CakePHP 构建类似查询或以这种方式使用 newExpr()
的示例。弄了好久,可以作为参考。
我最终选择的工作选项是:
$query->select([
// regular calculated columns
'salesTotal' => $query->func()->sum('ExampleTable.total'),
'salesQuantity' => $query->func()->sum('ExampleTable.quantity'),
// calculate again, without reusing any previously calculated results
'calcPrice' => $query->newExpr([
$query->func()->sum('ExampleTable.total'),
$query->func()->sum('ExampleTable.quantity'),
])->setConjunction('/'),
]);
我不喜欢我不能重用计算,如果有更好的方法,我很乐意学习。
根据您的建议,我将此作为使用 SET + 变量的简历:
控制器:
$weeks = $this->Facturas->find('Weeks', $options)->fetchAll('assoc');
型号:
public function findWeeks(Query $query, array $options = []) {
$conn = ConnectionManager::get('default');
$conn->execute('SET @row_number = 0');
$query = 'SELECT @row_number:=@row_number + 1) AS week_number FROM weeks';
$stmt = $conn->execute($query);
return $stmt;
}
我正在使用 CakePHP 3.8
由于您没有绑定任何值,因此您可以简单地按字面意思编写这些子句,而不会有任何复杂性。像这样:
$query
->select(array(
'@earnings := (`house_rent`+`conveyance`+`medical`+`dearness`+`others_allowances`) AS earnings',
'@deductions := (`income_tax`+`pro_tax`+`emp_state_insu`+`absence_fine`+`others_deductions`) AS deductions',
'@earnings - @deductions AS net_salary',
))
->from('salary')
;
我没有填充的 table 来测试它并确定它 return 你想要的,但它确实 return 这个结构的空数组(而不是抛出异常)使用 CakePHP:
CREATE TABLE salary (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
house_rent INT DEFAULT 0,
conveyance INT DEFAULT 0,
medical INT DEFAULT 0,
dearness INT DEFAULT 0,
others_allowances INT DEFAULT 0,
income_tax INT DEFAULT 0,
pro_tax INT DEFAULT 0,
emp_state_insu INT DEFAULT 0,
absence_fine INT DEFAULT 0,
others_deductions INT DEFAULT 0
);
这是我需要的 an example 个:
SELECT
@earnings := (`house_rent`+`conveyance`+`medical`+`dearness`+`others_allowances`) AS earnings ,
@deductions := (`income_tax`+`pro_tax`+`emp_state_insu`+`absence_fine`+`others_deductions`) AS deductions,
@earnings - @deductions AS net_salary
FROM
salary
在我的例子中,我需要一个 SUM(Table.total)
作为单独的 salesTotal
列返回,并在 @salesTotal/@salesQuantity
.
这是我尝试过的:
1.
$query->select([
$query->newExpr([
'@salesTotal := ',
$query->func()->sum('Table.total')
]),
]);
这会生成 @salesTotal := AND SUM(Table.total)
2.
$query->select([
$query->newExpr([
'@salesTotal := ' . $query->func()->sum('Table.total')
]),
]);
结果 警告 (4096):class Cake\Database\Expression\FunctionExpression 的对象无法转换为字符串
3.
$query->select([
$query->newExpr([
'@salesTotal := SUM(Table.total)'
]),
]);
正在收到 警告 (2):array_combine(): Both parameters should have an equal number of elements CORE/src/ORM/ResultSet.php, line 527. It's
灵感来自 this answer, the idea was to have the variables declared, and then reused for calculating some other value. This approach could be valuable especially with complex calculations. I used \Cake\ORM\Query::newExpr()
with an edited conjunction。
此外,根据 the MySQL doc on user-defined variables,我试着 SET
提前。
In addition, the default result type of a variable is based on its type at the beginning of the statement. This may have unintended effects if a variable holds a value of one type at the beginning of a statement in which it is also assigned a new value of a different type.
To avoid problems with this behavior, either do not assign a value to and read the value of the same variable within a single statement, or else set the variable to 0, 0.0, or '' to define its type before you use it.
这是我得到的查询:
$connection = $this->{'Example/Table'}->getConnection();
$connection->execute('SET @varSalesTotal = 0.0;');
$connection->execute('SET @varSalesQuantity = 0;');
$query = $this->{'Example/Table'}->find('all', [
// ...
]);
$query->select([
// calculate the @varSalesTotal variable
// SQL: @varSalesTotal := SUM(ExampleTable.total)
'varSalesTotalCol' => $query->newExpr([
'@varSalesTotal',
$query->func()->sum('ExampleTable.total'),
])->setConjunction(':='),
// calculate the @varSalesQuantity variable
// SQL: @varSalesQuantity := SUM(ExampleTable.quantity)
'varSalesQuantityCol' => $query->newExpr([
'@varSalesQuantity',
$query->func()->sum('ExampleTable.quantity'),
])->setConjunction(':='),
// attempt to calculate another value reusing the variables
// SQL: @varSalesTotal/@varSalesQuantity AS calcPriceVar
'calcPriceVar' => $query->newExpr([
'@varSalesTotal',
'@varSalesQuantity',
])->setConjunction('/'),
]);
注意:varSalesTotalCol
和 varSalesQuantityCol
键是必需的,否则我会得到
Warning (2): array_combine(): Both parameters should have an equal number of elements [CORE/src/ORM/ResultSet.php, line 527]
Warning (4096): Argument 1 passed to Cake\ORM\Entity::__construct() must be of the type array, boolean given, called in vendor/cakephp/cakephp/src/ORM/ResultSet.php on line 601 and defined [CORE/src/ORM/Entity.php, line 48]
最终结果,calcPriceVar
为空,显然这没有用。可能是因为:
The order of evaluation for expressions involving user variables is undefined. For example, there is no guarantee that SELECT @a, @a:=@a+1 evaluates @a first and then performs the assignment.
我仍在发布这个,因为我找不到任何使用 CakePHP 构建类似查询或以这种方式使用 newExpr()
的示例。弄了好久,可以作为参考。
我最终选择的工作选项是:
$query->select([
// regular calculated columns
'salesTotal' => $query->func()->sum('ExampleTable.total'),
'salesQuantity' => $query->func()->sum('ExampleTable.quantity'),
// calculate again, without reusing any previously calculated results
'calcPrice' => $query->newExpr([
$query->func()->sum('ExampleTable.total'),
$query->func()->sum('ExampleTable.quantity'),
])->setConjunction('/'),
]);
我不喜欢我不能重用计算,如果有更好的方法,我很乐意学习。
根据您的建议,我将此作为使用 SET + 变量的简历:
控制器:
$weeks = $this->Facturas->find('Weeks', $options)->fetchAll('assoc');
型号:
public function findWeeks(Query $query, array $options = []) {
$conn = ConnectionManager::get('default');
$conn->execute('SET @row_number = 0');
$query = 'SELECT @row_number:=@row_number + 1) AS week_number FROM weeks';
$stmt = $conn->execute($query);
return $stmt;
}
我正在使用 CakePHP 3.8
由于您没有绑定任何值,因此您可以简单地按字面意思编写这些子句,而不会有任何复杂性。像这样:
$query
->select(array(
'@earnings := (`house_rent`+`conveyance`+`medical`+`dearness`+`others_allowances`) AS earnings',
'@deductions := (`income_tax`+`pro_tax`+`emp_state_insu`+`absence_fine`+`others_deductions`) AS deductions',
'@earnings - @deductions AS net_salary',
))
->from('salary')
;
我没有填充的 table 来测试它并确定它 return 你想要的,但它确实 return 这个结构的空数组(而不是抛出异常)使用 CakePHP:
CREATE TABLE salary (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
house_rent INT DEFAULT 0,
conveyance INT DEFAULT 0,
medical INT DEFAULT 0,
dearness INT DEFAULT 0,
others_allowances INT DEFAULT 0,
income_tax INT DEFAULT 0,
pro_tax INT DEFAULT 0,
emp_state_insu INT DEFAULT 0,
absence_fine INT DEFAULT 0,
others_deductions INT DEFAULT 0
);