按一列或另一列对二维数组的行进行排序(如果第一列不存在)

问题描述 投票:0回答:2

在我的应用程序中,我对两个不同的表和两个不同的列名称执行关键字搜索。我想将

movies.title
people.title
组合起来,以便我可以按字母顺序将它们全部排序。目前,我合并了两个查询,结果首先返回电影,然后返回人物。

public function get_from_keyword($keyword)
{ 
    $movie_query = $this->db
    ->select('id, title, release_year')
    ->from('movies')
    ->like('movies.title', $keyword)
    ->where('movies.id IS NOT NULL', null)
    ->get()
    ->result();

    $person_query = $this->db
    ->select('name, person_id')
    ->from('people')
    ->like('name', $keyword)
    ->get()
    ->result();

    $merged_queries = array_merge($movie_query, $person_query);
    return $merged_queries;
}

我不确定是否需要动态更改

SELECT
查询中的列名称之一以便将它们合并在一起。

php mysql sorting codeigniter union
2个回答
1
投票

尝试使用“AS”来命名 movie.title 和 people.name 字段,如下所示:

   $person_query = $this->db
    ->select('name', 'MySortTitle') // AS
    ->select('person_id')
    ->from('people')
    ->like('name', $keyword)
    ->get()
    ->result();

电影查询也是如此:

    $movie_query = $this->db
    ->select('title', 'MySortTitle') // AS
    ->select('id, release_year')
    ->from('movies')
    ->like('movies.title', $keyword)
    ->where('movies.id IS NOT NULL', null)
    ->get()
    ->result();

然后通过 MySortTitle 对合并后的数组进行排序。


0
投票

无需重构模型方法来使用 ORDER BY 条件实现 UNION 查询,您只需在回调中使用

usort()
和回退。

现在,您有一个模型方法,它正在做两件事 - 它不应该这样设计,因为它限制了该方法的“实用性”/“可重用性”。 我建议在两个单独的模型中使用一个方法,并使用一个库来合并和排序。

简短的回答:

usort(
    $merged_results,
    fn($a, $b) => ($a->name ?? $a->title) <=> ($b->name ?? $b->title)
);

使用后备意味着您可以覆盖作为

$a
$b
传入的值的不可预测性,并且您不必改变模型方法来实现所需的有效负载。


长答案:

重申我之前的建议,合并和排序过程可能不理想地添加到模型层,当然不应该添加到控制器层(控制器不工作,它们委托工作)由其他层完成)。

您的控制器应该看起来像指令列表。您可能让控制器调用库来合并和排序数据

public function moviesAndActorsLike(string $term)
{
    $this->load->library('CinemaLib');
    $data['results'] = $this->CinemaLib->getPeopleAndMoviesLike($term);
    $this->CinemaLib->sortByTitleOrName($data['results']);
    $this->load->view('search', $data);
}

图书馆可能是逻辑的最佳场所。

public function getPeopleAndMoviesLike(string $term): array
{
    $this->load->model('People_model', 'PeopleModel');
    $this->load->model('Movies_model', 'MoviesModel');
    return array_merge(
        $this->PeopleModel->getLike('name', $term),
        $this->MoviesModel->getLike('title', $term)
    );
}

public function sortByTitleOrName(array &$mixedTableRecords): void
{
    usort(
        $mixedTableRecords,
        fn($a, $b) => ($a->name ?? $a->title) <=> ($b->name ?? $b->title)
    );
}
© www.soinside.com 2019 - 2024. All rights reserved.