我有2张桌子。表格具有相同的列,我需要比较它们。简单连接查询无法解决我的问题'因为table2可以包含适合表1的许多行,但我需要选择最合适的行。例如:
持续时间;价钱;数;
1; 3; 5;
持续时间;价钱;数;
1; 3.1; 5;
1; 3.01; 5;
我需要将table1中的row1与table2中的row1和row2进行比较并选择最合适的(例如row2是最合适的)并将row2标记为已比较,并且下次不进行比较。我正在使用FIREBIRD数据库和ADODB php库。我写了一些代码,但是当我在表中有很多记录时,它会工作很长时间。如何优化代码以更快地完成此任务?
代码:
$this->connect->BeginTrans();
$sourceResult = $this->connect->Execute( "SELECT SC_PHONE_NUMBER, SC_CALL_START, SC_DURATION, SC_RATE, SC_ID FROM ". $this->sourceTableName . " WHERE sc_comparing_id = " . $this->insertedId );
if ( $sourceResult ) {
while ( !$sourceResult->EOF ) {
$result = array();
$comparationResult = $this->connect->Execute(
"SELECT CC_PHONE_NUMBER, CC_CALL_START, CC_DURATION, CC_RATE, CC_ID FROM " . $this->comparableTableName . " WHERE cc_comparing_id = " . $this->insertedId
. " AND cc_is_compared = 0"
. " AND cc_phone_number = " . $sourceResult->fields['SC_PHONE_NUMBER']
. " AND " . $sourceResult->fields['SC_CALL_START'] . " BETWEEN cc_call_start - " . TIME_RANGE . " AND " . " cc_call_start + " . TIME_RANGE
);
if ( $comparationResult ) {
while ( !$comparationResult->EOF ) {
$callStartRating = TIME_RANGE / ( TIME_RANGE + abs( $sourceResult->fields['SC_CALL_START'] - $comparationResult->fields['CC_CALL_START'] ) );
$durationRating = 0;
$rateRating = 0;
if ( $sourceResult->fields['SC_DURATION'] > $comparationResult->fields['CC_DURATION'] ) {
$durationRating = $comparationResult->fields['CC_DURATION'] / $sourceResult->fields['SC_DURATION'];
} else {
$durationRating = $sourceResult->fields['SC_DURATION'] / $comparationResult->fields['CC_DURATION'];
}
if ( $sourceResult->fields['SC_RATE'] > $comparationResult->fields['CC_RATE'] ) {
$rateRating = $comparationResult->fields['CC_RATE'] / $sourceResult->fields['SC_RATE'];
} else {
$rateRating = $sourceResult->fields['SC_RATE'] / $comparationResult->fields['CC_RATE'];
}
$totalRating = $rateRating + $durationRating + $callStartRating;
$result[] = array(
'sc_id' => $sourceResult->fields['SC_ID'],
'cc_id' => $comparationResult->fields['CC_ID'],
'rating' => $totalRating
);
$comparationResult->MoveNext();
}
$resArray = null;
if ( count( $result ) >= 1 ) {
$resArray = $result[0];
foreach ( $result as $row ) {
if ( $resArray['rating'] < $row['rating'] ) {
$resArray = $row;
}
}
$query = "UPDATE source_cdr SET sc_cc_key = " . $row['cc_id'] . " WHERE sc_id = " . $row['sc_id'];
$this->connect->_Execute( $query );
$this->connect->_Execute( "UPDATE comparable_cdr SET cc_is_compared = 1 WHERE cc_id = " . $resArray['cc_id'] );
}
}
$this->connect->CommitTrans();
$sourceResult->MoveNext();
}
答案 0 :(得分:1)
不是你想要的答案,但为了加快速度,你应该尝试在SQL中回答这个问题。在您的顶部示例中,您将执行类似
的操作Select FIRST 1 duration, price, number
from tablea a
join tableb b on a.duration=b.duration and a.number = b.number
where b.price>=a.price
现在我确信你的表结构和比较更加复杂,也许你可以分享更多的数据结构和比较规则,这里的人可以提供帮助。
另一种有用但不理想的方法,确保您订购数据,如果发生最小比较,请退出循环。
答案 1 :(得分:1)
只有一个查询,您可以从comparativeTable获得“最佳”条目。
SELECT *
FROM `comparable_table`
ORDER BY ABS(CAST("3.00" AS DECIMAL) - `price`)
LIMIT 1
值“3.00”来自源表中的一行。
对于大型表格,此查询速度很慢。
如果你有一张大桌子,试试这个:
SELECT *
FROM
(
(
SELECT *
FROM `comparable_table`
WHERE `price` >= CAST("3.00" AS DECIMAL)
ORDER BY `price`
LIMIT 1
)
UNION DISTINCT
(
SELECT *
FROM `comparable_table`
WHERE `price` <= CAST("3.00" AS DECIMAL)
ORDER BY `price` DESC
LIMIT 1
)
) AS `min_max`
ORDER BY ABS(CAST("3.00" AS DECIMAL) - `price`)
LIMIT 1
如果你在price
上添加一个索引,那么这个查询就会使用它,而且在大型表上它应该更快。