比较2个表中的每一行

时间:2013-09-19 13:35:33

标签: php mysql sql firebird

我有2张桌子。表格具有相同的列,我需要比较它们。简单连接查询无法解决我的问题'因为table2可以包含适合表1的许多行,但我需要选择最合适的行。例如:

表1

持续时间;价钱;数;
1; 3; 5;


表2

持续时间;价钱;数;
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();
            }

2 个答案:

答案 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上添加一个索引,那么这个查询就会使用它,而且在大型表上它应该更快。