如何使用select和join to zend framework 1.11模型转换非常长的mysql查询

时间:2012-08-04 14:03:55

标签: mysql database zend-framework

我有这个mysql查询:

SELECT 
    freeAnswers.*, 
    (SELECT `districtCode` 
         FROM `geodatas` 
         WHERE `zipCode` = clients.zipCode 
         GROUP BY `zipCode` 
         LIMIT 0, 1) as districtCode, 
    clients.zipCode, 
    clients.gender, 
    clients.startAge, 
    clients.endAge, 
    clients.mail, 
    clients.facebook, 
    surveys.customerId, 
    surveys.activityId, 
    surveys.name as surveyName, 
    customers.companyName, 
    activities.name as activityName 
    FROM freeAnswers, 
         clients, 
         surveys, 
         customers, 
         activities 
    WHERE freeAnswers.surveyId = surveys.id 
         AND surveys.customerId = customers.id 
         AND activities.id = surveys.activityId 
         AND clients.id = freeAnswers.clientId 
         AND customers.id = 1 
    ORDER BY activityName asc 
    LIMIT 0, 10

我的mysql服务器上的查询是正确的,但是当我尝试在Zend Framework 1.11模型中使用它时 我收到此错误:Mysqli准备错误:操作数应包含1列

拜托,有人可以帮助我让它运行良好吗?

最诚挚的问候, Elaidon

1 个答案:

答案 0 :(得分:0)

以下是一些应该有效的代码。 Zend_Db_Select并没有真正提供从FROM子句中选择多个表而不使用JOIN的方法,因此对于查询的一小部分,这对我来说感觉有些骚动。您最好的选择可能是在适当的时候使用JOIN重写查询。

    $subselect = $db->select()
                    ->from('geodatas', 'districtCode')
                    ->where('zipCode = clients.zipCode')
                    ->group('zipCode')
                    ->limit(1, 0);

    $from   = $db->quoteIdentifier('freeAnswers') . ', ' .
              $db->quoteIdentifier('clients')     . ', ' .
              $db->quoteIdentifier('surveys')     . ', ' .
              $db->quoteIdentifier('customers')   . ', ' .
              $db->quoteIdentifier('activities');

    $select = $db->select()
                 ->from(array('activities' => new Zend_Db_Expr($from)),
                        array('freeanswers.*',
                              'districtCode' =>
                                  new Zend_Db_Expr('(' . $subselect . ')'),
                              'clients.zipCode', 'clients.gender', 'clients.startAge',
                              'clients.endAge', 'clients.mail', 'clients.facebook',
                              'clients.customerId', 'clients.activityId',
                              'surveyName' => 'surveys.name', 'customers.companyName',
                              'activityName' => 'activities.name'))
                 ->where('freeAnswers.surveyId = surveys.id')
                 ->where('surveys.customerId = customers.id')
                 ->where('activities.id = surveys.activityId')
                 ->where('clients.id = freeAnswers.clientId')
                 ->where('customers.id = ?', 1)
                 ->order('activityName ASC')
                 ->limit(10, 0);

我说它是hackish的唯一原因是因为这条线:

->from(array('activities' => new Zend_Db_Expr($from)),

由于from()实际上只适用于一个表,因此我创建了一个Zend_Db_Expr并将相关性指定为表达式中的最后一个表名。如果你没有传递Zend_Db_Expr,它将错误地引用逗号分隔的表名,或者如果传递一个表名数组,它只使用第一个。当您传递没有名称的Zend_Db_Expr时,默认使用AS t,这在您的情况下也不起作用。这就是为什么我把它原样。

除了提到的最后一件事之外,它返回你提供的确切SQL。这实际上是它返回的内容:

SELECT
`freeanswers`.*,
(SELECT `geodatas`.`districtCode`
    FROM `geodatas`
    WHERE (zipCode = clients.zipCode)
    GROUP BY `zipCode`
    LIMIT 1) AS `districtCode`,
`clients`.`zipCode`,
`clients`.`gender`,
`clients`.`startAge`,
`clients`.`endAge`,
`clients`.`mail`,
`clients`.`facebook`,
`clients`.`customerId`,
`clients`.`activityId`,
`surveys`.`name` AS `surveyName`,
`customers`.`companyName`,
`activities`.`name` AS `activityName`
FROM `freeAnswers`,
     `clients`,
     `surveys`,
     `customers`,
     `activities` AS `activities`
WHERE (freeAnswers.surveyId = surveys.id)
AND (surveys.customerId = customers.id)
AND (activities.id = surveys.activityId)
AND (clients.id = freeAnswers.clientId)
AND (customers.id = 1)
ORDER BY `activityName` ASC
LIMIT 10

这样可行但最终你会想要使用JOIN重写它,而不是指定大多数WHERE子句。

在处理子查询和Zend_Db_Select时,我发现在编写最终查询之前将每个子查询编写为自己的查询很容易,只需将子查询插入需要去的位置,Zend_Db处理其余部分。

希望有所帮助。