Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 如何在Yii CDbCriteria中控制sql连接顺序;加上;_Mysql_Activerecord_Join_Yii_Database Relations - Fatal编程技术网

Mysql 如何在Yii CDbCriteria中控制sql连接顺序;加上;

Mysql 如何在Yii CDbCriteria中控制sql连接顺序;加上;,mysql,activerecord,join,yii,database-relations,Mysql,Activerecord,Join,Yii,Database Relations,对于findAll语句,我有以下标准 $with=array( 'tumor'=>array( 'select'=>false, 'joinType'=>'INNER JOIN', ), 'tumorLibraryType'=>array( 'select'=>false, 'joinType'=>'INNER JOIN', 'condition'=>'tumorLibraryType.id

对于findAll语句,我有以下标准

$with=array(
    'tumor'=>array(
    'select'=>false,
    'joinType'=>'INNER JOIN',
    ),
    'tumorLibraryType'=>array(
    'select'=>false,
    'joinType'=>'INNER JOIN',
    'condition'=>'tumorLibraryType.id = 1 OR tumorLibraryType.id = 6',
    ),  
    'tumorPatient'=>array(
    'select'=>false,
    'joinType'=>'INNER JOIN',
    )
);

$libPairs=LibraryPairs::model()->with($with)->findAll();
以下是相关的模型关系:

    'tumor' => array(self::BELONGS_TO, 'Libraries', array('tumor_library'=>'id')),
    'normal' => array(self::BELONGS_TO, 'Libraries', array('normal_library'=>'id')),        
    // making separate AR routes for tumor and normal. only tumor used currently
    'tumorLibraryType'=>array(self::HAS_ONE,'LibraryTypes','','on'=>'tumor.library_type_id = tumorLibraryType.id'),
    'tumorLibrariesIsolates'=>array(self::HAS_MANY,'LibrariesIsolates',array('id'=>'library_id'),'through'=>'tumor'),
    'tumorSamplesIsolates'=>array(self::HAS_MANY,'SamplesIsolates',array('isolate_id'=>'isolate_id'),'through'=>'tumorLibrariesIsolates'),
    'tumorSamples'=>array(self::HAS_MANY,'Samples',array('sample_id'=>'id'),'through'=>'tumorSamplesIsolates'),
    'tumorPatient'=>array(self::HAS_ONE,'Patients',array('patient_id'=>'id'),'through'=>'tumorSamples'),
此代码生成以下sql:

SELECT `t`.`tumor_library` AS `t0_c0`, `t`.`normal_library` AS `t0_c1`, `t`.`created` AS `t0_c2`, `t`.`created_by` AS `t0_c3`, `t`.`last_modified` AS `t0_c4`, `t`.`last_modified_by` AS `t0_c5`, `tumor`.`library_type_id` AS `t1_c2`, `tumor`.`id` AS `t1_c0` 
FROM `library_tumor_normal_pairs` `t` 
INNER JOIN `library_types` `tumorLibraryType` ON (tumor.library_type_id = tumorLibraryType.id) 
INNER JOIN `libraries` `tumor` ON (`t`.`tumor_library`=`tumor`.`id`) 
LEFT OUTER JOIN `libraries_isolates` `tumorLibrariesIsolates` ON (`tumor`.`id`=`tumorLibrariesIsolates`.`library_id`) 
LEFT OUTER JOIN `samples_isolates` `tumorSamplesIsolates` ON (`tumorLibrariesIsolates`.`isolate_id`=`tumorSamplesIsolates`.`isolate_id`) 
LEFT OUTER JOIN `samples` `tumorSamples` ON (`tumorSamplesIsolates`.`sample_id`=`tumorSamples`.`id`) 
INNER JOIN `patients` `tumorPatient` ON (`tumorSamples`.`patient_id`=`tumorPatient`.`id`) 
WHERE (tumorLibraryType.id = 1 OR tumorLibraryType.id = 6) 
但是sql抛出了一个错误:

“未找到列:1054“on子句”中的未知列“tumor.library\u type\u id”。

但是,如果我简单地将sql查询中的肿瘤行上移到第一个join语句,并手动运行查询,那么查询就会工作

SELECT `t`.`tumor_library` AS `t0_c0`, `t`.`normal_library` AS `t0_c1`, `t`.`created` AS `t0_c2`, `t`.`created_by` AS `t0_c3`, `t`.`last_modified` AS `t0_c4`, `t`.`last_modified_by` AS `t0_c5`, `tumor`.`library_type_id` AS `t1_c2`, `tumor`.`id` AS `t1_c0` 
FROM `library_tumor_normal_pairs` `t` 
INNER JOIN `libraries` `tumor` ON (`t`.`tumor_library`=`tumor`.`id`) 
INNER JOIN `library_types` `tumorLibraryType` ON (tumor.library_type_id = tumorLibraryType.id) 
LEFT OUTER JOIN `libraries_isolates` `tumorLibrariesIsolates` ON (`tumor`.`id`=`tumorLibrariesIsolates`.`library_id`) 
LEFT OUTER JOIN `samples_isolates` `tumorSamplesIsolates` ON (`tumorLibrariesIsolates`.`isolate_id`=`tumorSamplesIsolates`.`isolate_id`) 
LEFT OUTER JOIN `samples` `tumorSamples` ON (`tumorSamplesIsolates`.`sample_id`=`tumorSamples`.`id`) 
INNER JOIN `patients` `tumorPatient` ON (`tumorSamples`.`patient_id`=`tumorPatient`.`id`) 
WHERE (tumorLibraryType.id = 1 OR tumorLibraryType.id = 6) 

所以我的问题是,如何控制Yii中“with”条件的sql连接顺序?可能吗?正如您所看到的,我的'with'数组和关系在其他数组之前有'tum',但是连接顺序没有保留。

这行看起来不正确:

'tumorLibraryType'=>array(self::HAS_ONE,'LibraryTypes','','on'=>'tumor.library_type_id = tumorLibraryType.id'),
也许应该是这样

'tumorLibraryType'=>array(self::HAS_ONE,'LibraryTypes',array('id'=>'library_type_id'),'through'=>'tumor'),

我遇到了一个类似的问题:Yii生成连接的顺序使得SQL语句无效。例如,当您试图编写依赖于通过
$CDBCriteria->with
传递的关系中指定的表的自定义
$CDBCriteria->join
时,就会出现这种情况。这是因为
join
CJoinQuery::\uu构造函数
中处理,而所有的“标准”联接(从
)都是由Yii在
CJoinQuery::join
中生成的,即在构造函数之后

不幸的是,除了补丁之外,没有其他解决方案。以下是我如何在我的Yii副本中执行此操作的示例(代码按“原样”提供)-请检查它是否适用于您的案例

首先,我们需要在
CDbCriteria
中添加一个字段,它将打开/关闭一个新选项

CDbCriteria.php

class CDbCriteria extends CComponent
{
  ...

  /**
   * @var string how to join with other tables. This refers to the JOIN clause in an SQL statement.
   * For example, <code>'LEFT JOIN users ON users.id=authorID'</code>.
   */
  public $join='';

  /**
   * Patch begins: 
   */
  public $joinreorder = false; // new option
  ...
class CJoinQuery
{
  ...

  /**
   * @var array list of join element IDs (id=>true)
   */
  public $elements=array();

  /**
   * Patch begins: 
   */
  private $joinreorder = false; // the same new option
  private $postjoins; // the variable to store our custom joins
  ...
其次,我们需要扩展
CJoinQuery
(请注意,它位于CActiveFinder.php中):

CActiveFinder.php

class CDbCriteria extends CComponent
{
  ...

  /**
   * @var string how to join with other tables. This refers to the JOIN clause in an SQL statement.
   * For example, <code>'LEFT JOIN users ON users.id=authorID'</code>.
   */
  public $join='';

  /**
   * Patch begins: 
   */
  public $joinreorder = false; // new option
  ...
class CJoinQuery
{
  ...

  /**
   * @var array list of join element IDs (id=>true)
   */
  public $elements=array();

  /**
   * Patch begins: 
   */
  private $joinreorder = false; // the same new option
  private $postjoins; // the variable to store our custom joins
  ...
现在我们可以更改
CJoinQuery
构造函数:

CActiveFinder.php(续)

如果
joinreorder
true
我们将自定义联接存储在新成员变量
postjoins
中。否则,所有这些都应该像以前一样工作

现在是
CJoinQuery::createCommand
中的实际修复:

CActiveFinder.php(续)

最后,我们将自定义联接添加到SQL语句中,并将它们附加到从Yii的关系生成的其他联接中(不像在标准实现中那样预先添加)

现在我们可以这样使用它:

$criteria = new CDbCriteria;
$criteria->joinreorder = true;
$criteria->with = array('product', 'shop');
$criteria->join = 'LEFT OUTER JOIN `shop2address` `s2a` ON (`shop`.`id` =  `s2a`.`shop_id`)';
如果不使用
joinreorder=true
,则会生成错误,指出ON子句中的
shop.id
列未知,因为“shop”表尚未添加到SQL语句中。使用
joinreorder=true
它可以按预期工作

对于只使用
with
的情况,并且生成了不正确的连接顺序,应该应用更复杂的补丁。它涉及
CJoinQuery::join
方法。它可能应该有一个可选参数
$priority
,可以通过添加到
CDbCriteria
中的相应成员再次填充该参数。然后在
CJoinQuery::join
中更改以下行:

$this->joins[$element->priority]=$element->getJoinCondition();
$this->joins[$element->priority]=$element->relation->join;

这允许根据指定的优先级以任意方式重新排序联接。

伙计们,我想我来晚了

我也有类似的问题

我对合并有以下标准:

    $criteria = new CDbCriteria();

    $criteria->with = [
       'codebaseName' => [
          'alias' => 'cn'
       ],
       'codebaseProducer' => [
          'alias' => 'cp'
       ],
       'registrationDocumentLast' => [
          'alias' =>'rdl'
       ]

    ];
它以这样的顺序结束:

ORDER BY COALESCE(cn.name_our,cn.name_supplier), id DESC LIMIT 50
我没有明确指定按id DESC排序

在玩了一番之后,我发现它来自关系注册DocumentLast,它被定义为

      'registrationDocumentLast' => [
          self::HAS_ONE, RegistrationDocument::class, 'codebase_product_pharm_id',
          'joinType' => 'LEFT JOIN',
          'order' => 'id DESC'
       ],
看看订单键。从

          'order' => 'id DESC'


解决了当多个关系“通过”同一个关系时出现“非唯一表别名”错误的问题。确定。但是您可以指定别名:这并不能解决表别名不唯一的问题,因为它会使用相同的别名创建额外的联接,或者需要冗余联接和“通过”关系,这会降低速度。这是一个记录在案的问题,上面的解决方案是最有效的。我最终以另一种方式解决了这个问题,但如果有人知道如何使用“with”来控制连接顺序,我仍然想知道如何。这太好了。我还没有测试过你的解决方案,但你是否在Yii论坛上发布过?它可能会被合并到未来的版本中。@glyph当它完成时,我可能会发布一个解决方案,这意味着用
s在
中重新排序。
          'order' => 't.id DESC'