【问题标题】:Better way to do this SQL by using YII CDbCriteria or find() methods?通过使用 YII CDbCriteria 或 find() 方法来执行此 SQL 的更好方法?
【发布时间】:2014-09-12 11:24:16
【问题描述】:

我有一个简单的SQL 查询,我想通过Yii 1.15 ORM 运行。

SQL 语法

SELECT ( sum(last_question) - count(last_question) ) as data 
FROM tbl_game 
WHERE last_question <> 0

我的问题是

  1. Yii 的更好方法是什么?

  2. 如果使用 Yii,是否可以返回整数值而不是 CModel Object

更新 1:

我已经尝试过类似的方法。它永远不会返回question_answered。我不知道它为什么这样做。如果CDbCriteriaselect 这样的选项,那么它应该可以工作。

    $criteria = new CDbCriteria;
    $criteria->select    = '( sum(`last_question`) - count(`last_question`) ) as "question_answered" ';
    $criteria->condition = "last_question <> 0";
    return game::model()->find($criteria);

更新 2:

这是上述标准返回模型的原始输出。这里没有question_answered

我确定表中有记录。

我也按照建议将 " 替换为 '。它仍然没有给出question_answered

object(game)[103]
public 'points' => null
private '_new' (CActiveRecord) => boolean false
private '_attributes' (CActiveRecord) => 
  array (size=0)
    empty
private '_related' (CActiveRecord) => 
  array (size=0)
    empty
private '_c' (CActiveRecord) => null
private '_pk' (CActiveRecord) => null
private '_alias' (CActiveRecord) => string 't' (length=1)
private '_errors' (CModel) => 
  array (size=0)
    empty
private '_validators' (CModel) => null
private '_scenario' (CModel) => string 'update' (length=6)
private '_e' (CComponent) => null
private '_m' (CComponent) => null

【问题讨论】:

  • 它永远不会给你一些'question_answered'。您正在执行Model-&gt;find(),它将始终返回活动记录或 null。你不能在其中填写一个复杂的选择并返回一个模型,因为 Yii 不知道如何将结果映射到一个模型。 Find 更像是一个记录过滤器。您在这里选择的实际上是什么?你到底想收到什么?
  • question_answered 来自第一个 SQL 查询。我知道它不可能得到 int,我会得到 CModel。但是为什么我不能用 CDbCriteria 来做这件事
  • 因为你得到(并且想要?)一个整数,但 Model-&gt;find() 将返回一个活动记录模型或 null。用 find() 来做这件事是没有意义的。这个整数是多少?一个模型的 ID 还是只是一个计数?如果它与模型(如 ID)无关,则通过 find() 获取它是没有意义的。
  • 如果您阅读了这个问题,last_question 是我计算的基础。它是一个整数值。这就是我想用这个字段返回sum(last_question) - count(last_question)

标签: php yii


【解决方案1】:

我想我有一个适合你的解决方案。 您遇到的主要问题是,您想要选择模型中不存在的字段('question_answered')。因此,您需要做的就是将此字段添加到模型中。

型号:

class Game extends CActiveRecord {
  ...
    public $question_answered;
  ...
}

那么你可以这样做:

    $criteria = new CDbCriteria;
    $criteria->select = '(sum(`last_question`)-count(`last_question`)) as question_answered';
    $criteria->condition = "last_question <> 0";
    echo Game::model()->find($criteria)->question_answered;

每次在select 子句中添加不存在的字段时,都必须在模型中添加该字段。

希望这会有所帮助,它对我有用。

【讨论】:

  • 你想如何避免它?
  • 我将使用其他一些现有属性,如id 来获取临时结果。因为它主要是标量获取查询,所以它不会受到伤害:)
【解决方案2】:

要直接获取值而不是作为模型,您可以使用 DAO/PDO:

$sql = 'SELECT SUM(`last_question`) - COUNT(`last_question`) AS data
FROM tbl_game
WHERE last_question <> :param';
$connection = Yii::app()->db;
$command = $connection->createCommand($sql);
$value = $command->queryScalar(array(':param' => 0));

$value 是找到的第一条记录。 如果你想要多条记录,你可以使用$values = $command-&gt;queryAll(true, array(':param' =&gt; 0)) 返回一个数组。

More info here.

【讨论】:

  • 我的意思是使用 CDBcriteria 或 find 方法来执行它。有可能吗?
  • 我指的是您的第二个问题“获取 int 而不是模型”。您可以像上面写的那样使用 CDbCriteria 来做到这一点。只需从您的选择中取出双引号即可。你拿回来的是什么?某种身份证?如果是这样,您还必须使用 findByPk 检索模型。
【解决方案3】:

您可以使用另一种巧妙的选择,我不确定它是否适用于您的情况。如果您有一些模型与具有 last_question 属性的模型相关,并且关系是 HAS_MANYMANY_MANY,您可以定义 STAT em> 关系在您的第一个模型中,而不是像任何其他关系一样调用。

public function relations()
{
    return array(
        'someVariableName'=>array(self::STAT, 'ModelNameWhichYouRelateto', 'foreignkey_attr', array(
            'select'=>'SUM(last_question) - COUNT(last_question)',
            'condition'=>'last_question <> 0'
        )),
    );
}

然后你可以简单地调用它

$model->someVariableName

并得到一个整数。

【讨论】:

  • last_question 在同一张表中,所以我不能使用关系
【解决方案4】:

您可以使用Query Builder

Yii::app()->db->createCommand()
    ->select('SUM(`last_question`) - COUNT(`last_question`)') // if using "()", than you have to escape columns names manualy.
    ->from('tbl_game')
    ->where('last_question != :param', [':param' => 0])
    ->queryScalar();

使用 CDbCriteria,尝试这样的事情(未测试):

$c = new CDbCriteria();
$c->select = 'SUM(`last_question`) - COUNT(`last_question`) AS "result"';
$c->addCondition('last_question != :param');
$c->params = [':param' => 0];

Game::model()->find($c)->result;

【讨论】:

  • 是否可以通过 find 或 CDbCriteria 来完成,我主要关注的是使用 find 方法选择列。有可能吗?
  • 是的,但我已经尝试过了。请参阅更新的问题。它永远不会返回“结果”
  • @sushant 因为你要返回完整模型,所以只返回return game::model()-&gt;find($criteria)-&gt;question_answered;
  • 对象没有任何名为 question_answered 的属性 :(
  • 在模型中创建类属性 public $result; 并使用带有 CDbCriteria 的 @Justinas 代码,它会起作用
猜你喜欢
  • 1970-01-01
  • 2012-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-08
相关资源
最近更新 更多