0

我有一列数据,其中包含一些数值,但有时其中包含 NULL 值,例如:

Name    Algebra   Band  Chemistry
Abel     3         6        2
Baker    5         NULL     4
Charlie  NULL      2        NULL
Delta    4         NULL     NULL

是否可以创建一个排序对象,以便在 Score 的两个方向上,NULL 值始终位于末尾?那是,

Name    Algebra [asc]  Band     Chemistry
Abel     3              6        2
Delta    4              NULL     NULL
Baker    5              NULL     4
Charlie  NULL           2        NULL

Name    Algebra [desc]  Band     Chemistry
Baker    5              NULL     4
Delta    4              NULL     NULL
Abel     3              6        2
Charlie  NULL           2        NULL

编辑:我应该在这里添加一个说明——我正在使用 ArrayDataProvider 因为这是一个汇总表,所以我不能在数据库端做任何事情——数据已经加载到本地数组中并且没有更多的数据库查询。

EDIT2:我收到了一些代码和更多关于我正在使用的结构的请求。因此,我对上面的示例进行了编辑,使其更接近我的实际情况。源数据如下所示:

[MySQL table and Yii model "Scores"]
Name     Class         Score
Abel     Algebra        3
Abel     Band           6
Abel     Chemistry      2
Baker    Algebra        5
Baker    Chemistry      4
Charlie  Band           2
Delta    Algebra        4

以下是代码的相关部分:

  $data = [];
  $items = Scores::find()->all();
  foreach ($items as $item) {
    $data[$item->name]['Name'] = $item->name;
    $data[$item->name][$item->class] = $item->score;
  }
  $arrayData = ArrayHelper::toArray($data);
  $arrayDataProviderInit = [
    'allModels' => $arrayData,
    'pagination' => [
      'pageSize' => 0,
    ],
    'sort' => [
      'attributes' => [
        'Name',
        // WHAT GOES HERE????
      ],
    ],
  ];
  $arrayDataProvider = new ArrayDataProvider($arrayDataProviderInit);
  $gridViewInit = [
    'dataProvider' => $arrayDataProvider,
    'formatter' => ['class' => 'yii\i18n\Formatter','nullDisplay' => 'NULL'],
    'columns' => [
        'Name',
        'Algebra',
        'Band',
        'Chemistry',
    ],
  ];
  echo GridView::widget($gridViewInit);
4

2 回答 2

0

IS NULL您可以通过在实际排序之前添加表达式来重新定义特定属性的排序规则
这里是 ActiveDataProvider 的排序对象的用例

    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);
    $dataProvider->sort->attributes = ArrayHelper::merge($dataProvider->sort->attributes, [
        'score' => [
            'asc'  => [
                'IS NULL ' . static::tableName().'score' => SORT_DESC,
                static::tableName(). 'score '=> SORT_ASC
            ],
            'desc' => [
                'IS NULL ' . static::tableName().'score' => SORT_DESC,
                static::tableName(). 'score '=> SORT_DESC
            ],
        ],
    ]);

基本上每次您按分数排序时,都会生成一个表达式

ORDER BY IS NULL score DESC, score ASC --or  
ORDER BY IS NULL score DESC, score DESC 

确保您首先按值是否为空进行排序,然后按实际值进行排序


解决您的特定用例:

如果使用ArrayDataProvider基本上你可以使用相同的原理,只需要向你的数据数组添加另一个属性,并使用它来定义你的排序规则

foreach ($items as $item) {
  $data[$item->name]['Name'] = $item->name;
  $data[$item->name][$item->class] = $item->score;
  $data[$item->name]['hasScore'] = is_null($item->score);
}

$arrayDataProviderInit = [
  'allModels' => $arrayData,
  'pagination' => [
    'pageSize' => 0,
  ],
  'sort' => [
    'attributes' => [
      'Name',
      'Score' => [
        'asc' =>  ['hasScore' => SORT_ASC, 'Score' => SORT_ASC],
        'desc' => ['hasScore' => SORT_ASC, 'Score' => SORT_DESC],
      ],
    ],
  ],
];
于 2017-09-27T12:19:58.963 回答
0

设置排序属性,在 defaultOrder 中只使用属性名称,例如:

   defaultOrder => ['score' => SORT_ASC],

您不应该以默认顺序传递 db 表达式。

于 2017-09-27T13:08:09.017 回答