【问题标题】:how to make sure a record is always at the top in a given resultset in mysql?如何确保记录始终位于mysql中给定结果集中的顶部?
【发布时间】:2012-08-06 06:52:18
【问题描述】:

我有一个搜索查询,它根据输入参数生成一个结果集,并且可以根据不同的参数对结果进行排序 (ASC/DESC):价格、持续时间等(分页到位且限制为 10 条记录)

我现在有一个要求,如果我有一个 id 传入,我希望将相应的记录粘在给定结果集中的顶部。

假设我们有一个这样的包表:

Package
 - id
 - name
 - mPrice
 - vPrice
 - duration

// Searching pkg based on Price (in DESC order) where name = Thailand
sqlQuery = 
"SELECT p.id, p.name, p.mPrice, p.vPrice FROM package p 
WHERE p.name = LOWER('Thailand') 
ORDER BY (p.mPrice + p.vPrice) DESC 
LIMIT 10"

假设完整的结果集是 20 条 id 为 1 到 20 的记录。我现在需要返回 id 为 14 的记录以始终位于顶部。我想出了以下查询,但这不起作用:

sqlQuery = 
"SELECT p.id, p.name, p.mPrice, p.vPrice FROM package p 
WHERE p.name = LOWER('Thailand') or p.id = 14
ORDER BY CASE 
WHEN p.id=14 then 0 
else (p.mPrice + p.vPrice) 
end DESC 
LIMIT 10"

我对为什么这不起作用的猜测:在 order by 子句之后,结果集按降序排序,然后被截断为 10 条记录。 id=14 的记录可能不是此截断集的一部分。这是正确的吗?

如何让 id=14 的记录保持在顶部?

【问题讨论】:

    标签: mysql sql sql-order-by


    【解决方案1】:
    ORDER BY (p.id=14) DESC, (p.mPrice=p.vPrice) DESC
    

    p.id=14 如果条件为真则返回1,否则返回0,因此降序排序会将所需的行置于顶部。

    从比较中返回一个数字是 MySQL 的一项功能,您可以使用标准 SQL 编写:

    ORDER BY CASE WHEN (p.id=14) THEN 0 ELSE 1 END,
             CASE WHEN (p.mPrice=p.vPrice) THEN 0 ELSE 1 END
    

    我发现这比UNION 更容易阅读,而且性能可能更好。

    【讨论】:

    • 非常酷!早该想到这一点。但是,当我尝试使用 ASC 对其进行排序时,这不起作用,我不知道为什么。 ORDER BY (p.id=14) ASC, (p.mPrice = p.vPrice) ASC
    • p.id=14 如果条件为真则返回1,否则返回0。升序排序将0 放在首位,因此您想要的排在最后...
    • 啊哈!伟大的。我将根据 ASC/DESC 将相等运算符翻转为 id 。如果这可能比 UNION 表现更好,您有什么想法吗?
    • 我希望这比UNION 表现更好,但你应该用你的数据试试这个。如果您总是想用p.id=14 显示记录,即使它的name 不是thailand,则需要OR 以确保记录在列表中。如果您只希望它在顶部如果它是thailand,则删除ORORDER BY 子句只能对查询返回的数据进行排序,不会产生额外的记录。
    • 我正要使用联合,但这看起来干净多了。谢谢!
    【解决方案2】:

    使用联合始终将您的包放在顶部:

    SELECT id, name, mPrice, vPrice FROM package WHERE id = 14
    UNION
    SELECT p.id, p.name, p.mPrice, p.vPrice FROM package p 
    WHERE p.name = LOWER('Thailand') or p.id = 14
    ORDER BY (p.mPrice = p.vPrice) DESC
    LIMIT 9
    

    【讨论】:

    • UNION ALLUNION 操作快。
    • 但是你不想让 id 14 出现在顶部,并且再次出现在“body”中
    【解决方案3】:

    试试这个:

    order by 
     case when p.id=14 then then (select MAX(mPrice)+1 from package ) else
    (p.mPrice = p.vPrice)  end desc
    LIMIT 10
    

    代替 (select MAX(p.mPrice)+1 from package ) 你可以给出一个常量值,它总是一个最大值,像这样

     order by 
     case when p.id=14 then then 1000000 else
    (p.mPrice = p.vPrice)  end desc
    LIMIT 10
    

    这样会更有效率

    【讨论】:

    • 你能解释一下你在那个表达中做了什么吗?
    • @brainydexter:我只是得到 price 的最大值+1,所以它总是在顶部
    猜你喜欢
    • 1970-01-01
    • 2022-09-27
    • 2012-10-29
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多