【问题标题】:Mysql ORDER by date, but filter resultsMysql 按日期排序,但过滤结果
【发布时间】:2012-11-23 18:12:24
【问题描述】:

假设我有 4 个表 A,B,C,D,每个表中有记录和 datetime 字段。

目前我使用UNION ALLORDER BY Date DESC

问题是如果表A今天添加了10条记录,而表B昨天添加了10条记录,那么前10条结果都来自表A

是否可以获得按日期排序的记录,但在所有 4 个表之间混合它们?

第一条记录将是表 A 中最新添加的记录,然后是表 B 中最新添加的记录,然后是 C,然后是 D。然后像这样循环它们?

谢谢

【问题讨论】:

    标签: mysql


    【解决方案1】:

    我不确定这是否是您正在寻找的,但我认为您可以使用以下内容:

    SELECT
      A.*,
      datediff((select max(`date`) from A), `date`) as d_diff,
      1 as tab
    FROM A
    UNION ALL
    SELECT
      B.*,
      datediff((select max(`date`) from B), `date`) as d_diff,
      2 as tab
    FROM B
    ORDER BY d_diff, tab, `date` desc
    

    或者这个:

    SELECT * FROM (SELECT  A.* FROM A ORDER BY `date` desc limit 5) a
    UNION ALL
    SELECT * FROM (SELECT  B.* FROM B ORDER BY `date` desc limit 5) b
    ORDER BY `date` DESC
    

    根据您的 cmets,这应该可行,但也可能很慢:

    SELECT
      A.*,
      (select count(*) from A A1 where A1.dat>A.dat) as i,
      1 as tab
    FROM A
    UNION ALL
    SELECT
      B.*,
      (select count(*) from B B1 where B1.dat>B.dat) as i,
      2 as tab
    FROM B
    order by i, tab
    

    (可以使用变量更快,但我更喜欢纯 SQL)

    【讨论】:

    • 现在试了一下,它和按日期排序几乎一样——直接从一张表中提取 10 条记录。
    • @galgai 两个查询都返回来自所有表的混合记录,我将编辑我的第一个以使其像您想要的那样循环...让我知道,但我认为应该没问题... .
    • @galgai 日期有间隔?也许这就是问题所在......但我正在考虑......
    • fthiella,如果它给你任何提示,所有表都有标识它们的字段 - 表 A 具有其表名的字段,B.C.D 相同。我尝试按表名字段分组,但它只提取 4 条记录(每个表中的一条),因为只有 4 个表,这很完美,但我不知道如何循环它。
    • 仅在 2 个表上尝试了上述解决方案,执行时间为 2 分钟!但是前 10 条记录仍然来自一个表...
    【解决方案2】:

    不幸的是,MySQL 没有排名功能 - 但您可以使用变量来模拟它。我建议尝试以下方法:

    SELECT * FROM 
    (select *, @rownum := @rownum + 1 AS rank, 'A' as tbl 
     from (SELECT * FROM (SELECT  A.* FROM A ORDER BY `date` desc) sa) a, 
          (SELECT @rownum := 0) r
     union all
     select *, @rownum2 := @rownum2 + 1 AS rank, 'B' as tbl 
     from (select * from (SELECT  B.* FROM B ORDER BY `date` desc) sb) b, 
          (SELECT @rownum2 := 0) r2
     union all
     select *, @rownum3 := @rownum3 + 1 AS rank, 'C' as tbl 
     from (select * from (SELECT  C.* FROM C ORDER BY `date` desc) sc) c, 
          (SELECT @rownum3 := 0) r3
     union all
     select *, @rownum4 := @rownum4 + 1 AS rank, 'D' as tbl 
     from (select * from (SELECT  D.* FROM D ORDER BY `date` desc) sd) d, 
          (SELECT @rownum4 := 0) r4
    ) s
    order by rank, tbl
    

    或者,尝试类似:

    SELECT * FROM 
    (SELECT S.*, 
            @rownum := CASE WHEN @tblvar <> S.tbl THEN 0 ELSE @rownum+1 END AS rank, 
            @tblvar := S.tbl AS tblvar 
     FROM 
     (SELECT * FROM 
      (SELECT  A.*, 'A' as tbl FROM A
       UNION ALL
       SELECT  B.*, 'B' as tbl FROM B
       UNION ALL
       SELECT  C.*, 'C' as tbl FROM C
       UNION ALL
       SELECT  D.*, 'D' as tbl FROM D) U
      ORDER BY tbl, `date` desc) S,
     (SELECT @rownum := 0) R,
     (SELECT @tblvar := '!') T
    ) Q
    order by rank, tbl
    

    【讨论】:

    • num 代表什么?它给了我错误,就像没有这样的字段
    • 好的,我试过了,把 num 改成 *.老实说,我不知道这一切有什么作用,有这么多子查询,但显然这是有效的,而且速度并不慢。你是天才,谢谢!
    • daaaaaaamn,在我的本地机器上它工作正常,但在实时服务器上它抛出:mysqld-5.0.67-community-nt-log]选择的嵌套级别太高。哦,好吧。
    • @galgai:我已将 num 更正为 * - 这是我在尝试查询的变体时应该解决的问题。 “表” A、B、C 和 D 实际上是表,还是服务器上的视图或派生表?如果是后者,则此行为是一个已知错误,记录在此:bugs.mysql.com/bug.php?id=41156。 (通过 Bill Karwin 对这个问题的回答找到:stackoverflow.com/questions/9134320
    • 它们是实际的表格。它在那里说:建议修复:sql_yacc.yy:添加“Lex->nest_level--;”在“select_derived”或“'(' get_select_lex select_derived union_opt ')' opt_table_alias”规则的末尾。这个文件 sql_yacc.yy 在 mysql 文件夹中吗?我没找到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多