按可空列对 MySQL 结果集进行排序,首先是空值,然后是另一列

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

我正在为我的论坛创建一个“固定”功能,并且我正在寻找一种方法将我的固定主题放在数组的开头,以便它们“粘在”页面顶部。

如果主题未固定,则

topic_pinned=NULL
如果已固定,则
topic_pinned=0

数组按

topic_updated
排序。固定主题需要保持按
topic_updated
排序,同时位于页面顶部,然后固定主题下方是非固定主题,也按
topic_updated
排序。

主题数组(

$forum_topic_results
):

Array
(
    [0] => Array
        (
            [topic_id] => 4
            [topic_subject] => Test Subject #4
            [topic_date] => 2015-09-10 18:34:18
            [topic_by] => 1
            [topic_pinned] => 
            [topic_updated] => 2015-09-10 20:37:22
        )

    [1] => Array
        (
            [topic_id] => 3
            [topic_subject] => Test Subject #3
            [topic_date] => 2015-08-22 09:24:40
            [topic_by] => 1
            [topic_pinned] => 0
            [topic_updated] => 2015-09-04 22:02:31
        )

    [2] => Array
        (
            [topic_id] => 2
            [topic_subject] => Test Subject #2
            [topic_date] => 2015-08-15 10:56:00
            [topic_by] => 1
            [topic_pinned] => 
            [topic_updated] => 2015-09-04 19:45:32
        )

    [3] => Array
        (
            [topic_id] => 1
            [topic_subject] => Test Subject #1
            [topic_date] => 2015-08-30 19:48:17
            [topic_by] => 1
            [topic_pinned] => 0
            [topic_updated] => 2015-09-03 00:44:38
        )
)

PHP:

/**
 * getAllTopics
 *
 * Retreives the topics of the chosen category from the `forum_topics` table.
 *
 * @param   $cat_id
 * @access  public
 */
public function getAllTopics($cat_id=NULL)
{
    $database=$this->database;

    $database->query('SELECT topic_id, topic_subject, topic_date, topic_by, topic_pinned, topic_locked FROM forum_topics WHERE topic_cat = :catid ORDER BY topic_updated DESC', array(':catid' => $cat_id));
    $result = $database->statement->fetchAll(PDO::FETCH_ASSOC);

    return $result;
}

# Get topics
$forum_topic_results = $this->getAllTopics($_GET['cat']);
foreach($forum_topic_results as $forum_topic_row)
{
    # Get user's username.
    $topic_by=SearchUser($forum_topic_row['topic_by']);

    $data.='<tr>'.
        '<td>'.
            '<h3><a href="'.$_SERVER['PHP_SELF'].'?action=forum_posts&topic='.$forum_topic_row['topic_id'].'">'.$forum_topic_row['topic_subject'].'</a></h3>'.
            'by '.$topic_by['username'].' on '.date('D M d, Y g:i a', strtotime($forum_topic_row['topic_date'])).
        '</td>'.
    '</tr>';
}

我想要的结果:

Array
(
    [0] => Array
        (
            [topic_id] => 3
            [topic_subject] => Test Subject #3
            [topic_date] => 2015-08-22 09:24:40
            [topic_by] => 1
            [topic_pinned] => 0
            [topic_updated] => 2015-09-04 22:02:31
        )

    [1] => Array
        (
            [topic_id] => 1
            [topic_subject] => Test Subject #1
            [topic_date] => 2015-08-30 19:48:17
            [topic_by] => 1
            [topic_pinned] => 0
            [topic_updated] => 2015-09-03 00:44:38
        )

    [2] => Array
        (
            [topic_id] => 4
            [topic_subject] => Test Subject #4
            [topic_date] => 2015-09-10 18:34:18
            [topic_by] => 1
            [topic_pinned] => 
            [topic_updated] => 2015-09-10 20:37:22
        )

    [3] => Array
        (
            [topic_id] => 2
            [topic_subject] => Test Subject #2
            [topic_date] => 2015-08-15 10:56:00
            [topic_by] => 1
            [topic_pinned] => 
            [topic_updated] => 2015-09-04 19:45:32
        )
)
php mysql sorting sql-order-by resultset
3个回答
4
投票

换个方式。

在数据库表中将 PINNED 标记为 1。

未固定为 0。

之后只需添加(替换 ORDER BY)到您选择主题的查询中:

ORDER BY `topic_pinned` DESC, `topic_updated` DESC

1
投票

为了完整起见,如果您实际上仍然想要或需要通过 php 对数组执行此操作,我可能会选择使用 usort。它不需要制造柱状阵列。

usort 允许您编写函数或提供执行比较逻辑的匿名函数。由于您有一个数组数组,并且需要利用多个数组元素来完成比较,因此只要记住以下几点,您就可以轻松编写一个简单的比较函数:

比较函数必须返回一个小于、等于或 如果第一个参数被认为是大于零 分别小于、等于或大于第二个。

类似这样的东西(即兴的、未经测试的代码)

function cmp($a, $b) {
    if ($a['topic_pinned'] == $b['topic_pinned']) {
        // Have to compare Dates
        $adate = new DateTime($a['topic_updated']);
        $bdate = new DateTime($b['topic_updated']);
        return ($adate < $bdate) ? -1 : 1;
    } elseif ($a['topic_pinned'] == null) {
        return 1;
    } else {
        return -1;
    }  
}

usort($array, 'cmp');

正如您所看到的,由于需要将日期时间字符串转换为日期时间对象,以便您可以实际进行比较,这很快就会变得复杂。

在这种情况下使用 sql 数据库更好/更快/更容易的原因就更明显了。


0
投票

这应该有效:

<?php
$finalArr = $forum_topic_results;
foreach ($finalArr as $key => $row) {
    $topic_pinned[$key] = $row['topic_pinned'];
}
array_multisort($topic_pinned, SORT_DESC, $finalArr);
return $finalArr;
?>

有关

array_multisort
的更多信息:array_multisort

© www.soinside.com 2019 - 2024. All rights reserved.