2

我正准备把我的头发扯掉,以扔便便为生!

我有一个在 MySQL 中运行良好的 MySQL 查询

SELECT 
    p.ID AS DataID, 
    p.timestamp AS Timestamp, 
    sum(p.Value * v.Factor) AS Value,
    v.VirtualProfiles_id AS VProfileID 
FROM 
    profiledata p 
JOIN 
    profilevirtualjoin v 
ON 
    p.Profile_ID=v.Profile_ID 
WHERE 
    v.VirtualProfiles_id = 5
GROUP BY 
    v.Profile_ID, 
    p.timestamp 

但是当我尝试在 Delphi 的 SQLDataSet 中将其作为查询运行时

SQLDataSet2.Active := False;
SQLDataSet2.CommandText := 'SELECT p.ID AS DataID, p.timestamp AS Timestamp, sum(p.Value * v.Factor) AS Value,' +
   'v.VirtualProfiles_id AS VProfileID FROM profiledata p JOIN profilevirtualjoin v ON ' +
   'p.Profile_ID=v.Profile_ID WHERE v.VirtualProfiles_id = ' + InttoStr(5)
   +' GROUP BY v.Profile_ID, p.timestamp';
SQLDataSet2.Active := True;

我收到一个错误

First chance exception at $765BC41F. Exception class TDBXError with message 'Unknown column 'v.VirtualProfiles_id' in 'where clause''. Process EMVS.exe (7556)

如果有人能提供任何见解,我将不胜感激。

编辑:

我正在使用 MySQL 服务器 5.5 和 Delphi XE

我想做的是:

我有一个表格如下:

Profile:
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| ID          | int(11)      | NO   | PRI | NULL    | auto_increment |
| Designation | varchar(255) | YES  |     | NULL    |                |
| Description | text         | YES  |     | NULL    |                |
| UnitID      | int(11)      | NO   | PRI | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+

profiledata
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| ID         | int(11)  | NO   | PRI | NULL    | auto_increment |
| TimeStamp  | datetime | YES  |     | NULL    |                |
| Value      | double   | YES  |     | NULL    |                |
| Profile_ID | int(11)  | NO   | PRI | NULL    |                |
+------------+----------+------+-----+---------+----------------+

Virtualprofiles
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| Designation | varchar(45)  | NO   |     | NULL    |                |
| Description | varchar(255) | YES  |     | NULL    |                |
| Unit_ID     | int(11)      | NO   | PRI | 0       |                |
+-------------+--------------+------+-----+---------+----------------+

profilevirtualjoin
+--------------------+---------+------+-----+---------+----------------+
| Field              | Type    | Null | Key | Default | Extra          |
+--------------------+---------+------+-----+---------+----------------+
| id                 | int(11) | NO   | PRI | NULL    | auto_increment |
| VirtualProfiles_id | int(11) | NO   | PRI | NULL    |                |
| Profile_ID         | int(11) | NO   | PRI | NULL    |                |
| Factor             | double  | NO   |     | 1       |                |
+--------------------+---------+------+-----+---------+----------------+

我需要做的是“生成”一个新的配置文件,它是一组现有配置文件的总和。因此,必须对 profiledata 表中的数据求和,其中 ProfileID 包含在 virtualprofile 中并且时间戳值相等。

4

4 回答 4

4

问题

所以,问题是这样的。Delphi XE提供的 DBExpress 驱动程序只能处理动态 SQL 查询,不能处理 MySQL 查询。虽然 Dynamic SQL 与 MySQL 兼容,但反过来却不兼容。

引用 MySQL 手册(第 12.16.3 节):

在标准 SQL 中,包含 GROUP BY 子句的查询不能引用选择列表中未在 GROUP BY 子句中命名的非聚合列。

MySQL 扩展了 GROUP BY 的使用,以便选择列表可以引用未在 GROUP BY 子句中命名的非聚合列。

Delphi XE3 中包含的更新的 DBExpress 驱动程序包括对 MySQL 代码的特定支持,因此此限制不适用。

解决方法

这个问题的解决方案是在 MySQL 服务器中创建一个视图,并仅使用动态 SQL 兼容代码从 Delphi 调用它。最后,以下解决方法成功了:

在 MySQL 中:

CREATE VIEW `VirtualProfileData` AS
SELECT 
    p.ID AS DataID, 
    p.timestamp AS Timestamp, 
    sum(p.Value * v.Factor) AS Value,
    v.VirtualProfiles_id AS VProfileID 
FROM 
    profiledata p 
JOIN 
    profilevirtualjoin v 
ON 
    p.Profile_ID=v.Profile_ID 
GROUP BY 
    v.Profile_ID, 
    p.timestamp

然后在德尔福

SQLDataSet2.Active := False;
SQLDataSet2.CommandText := 'SELECT * FROM VirtualProfileData WHERE VProfileID = ' + InttoStr(5);
SQLDataSet2.Active := True;
于 2012-12-07T07:39:08.483 回答
1

您在此处更改了列的名称:

v.VirtualProfiles_id AS VProfileID

在那之后,在大多数情况下(涉及分组或聚合的情况除外),您需要通过新名称引用列。我认为这里就是这种情况。

尝试更改您的WHERE子句以改用别名:

WHERE v.VirtualProfiles_id = ' + InttoStr(5)
于 2012-12-06T12:04:45.327 回答
0

问题是Mysql类型和Delphi类型之间的兼容性尝试使用delphi的Basics Types

于 2013-03-08T15:00:30.473 回答
0

在我的情况下,从

SELECT * FROM table_name WHERE column_name = 'VALUE';

SELECT * FROM table_name WHERE column_name LIKE 'VALUE';

解决了问题并返回相同的结果。

我没有挖掘 dipper 来弄清楚发生了什么,但这是一个奇怪的错误,因为它适用于除特定列之外的所有其他列。

于 2019-02-06T11:36:30.163 回答