【问题标题】:How to get latest records如何获取最新记录
【发布时间】:2018-10-17 14:09:07
【问题描述】:

我有一张这样的表:

+--------+-------------+----------+---------+
| PK(id) | FK(user_id) | ctime    | comment |
+--------+-------------+----------+---------+
| 1      | 1           | 20170101 | "Haha"  |
+--------+-------------+----------+---------+
| 2      | 2           | 20170102 | "Nope"  |
+--------+-------------+----------+---------+
| 3      | 2           | 20170104 | "Geez"  |
+--------+-------------+----------+---------+
| 4      | 1           | 20170110 | "Gone"  |
+--------+-------------+----------+---------+

我希望检索每个FK(user_id) 的最新记录,如下所示:

+--------+-------------+----------+---------+
| PK(id) | FK(user_id) | ctime    | comment |
+--------+-------------+----------+---------+
| 3      | 2           | 20170104 | "Geez"  |
+--------+-------------+----------+---------+
| 4      | 1           | 20170110 | "Gone"  |
+--------+-------------+----------+---------+

所以我尝试了SELECT DISTINCT T.* FROM my_table AS T 和SELECT DISTINCT T.user_id FROM my_table AS T; 但是,它们不起作用!

我尝试了 GROUP BY 语句,如下所示,

SELECT T.* FROM my_table AS T GROUP BY `user_id` DESC

它确实像我期望的那样完美。 于是我开始想办法把SQL翻译成Django!

首先,我尝试使用 RawSQL:

from django.db.models.expressions import RawSQL

def _select_latest_rows(model_class, target_column_name, query_set=None):
    query_set = query_set or model_class.objects
    table_name = model_class._meta.db_table
    raw_sql = '''
    SELECT * FROM %s GROUP BY %s
    '''
    return query_set.annotate(val=RawSQL(raw_sql, (table_name, target_column_name,)))

每当我调用此函数时,Django 都会弹出以下错误。

django.db.utils.ProgrammingError: (1064, "You have an error in your SQL syntax
blah blah blah...

然后我检查了我的查询字符串:

print(_select_latest_rows(model_class, target_column_name, query_set).query)

然后它返回:

SELECT T.`id`, T.`user_id`, T.`ctime`, T.`comment`, (SELECT * FROM my_table GROUP BY user_id) AS `val` FROM my_table

好吧,我不得不说我对 SQL 语法不太熟悉,到目前为止,我还没有弄清楚这个查询字符串中错误的位置:(

我必须按照this answer 中的建议在模型的管理器实例中调用raw() 函数吗?

model_class.objects.raw('SELECT T.* FROM my_table AS T GROUP BY `user_id` DESC LIMIT 10 OFFSET 0')

或者我不应该在开头使用 GROUP BY 语句?

【问题讨论】:

标签: mysql sql django


【解决方案1】:

Oracle/PostgreSQL:

尝试使用下面的SQL,它会满足你的要求。

select id,user_id,ctime,comment
from  (select   id,user_id,ctime,comment
                rank() over(partition by user_id order by ctime desc) rn
        from your_table_name
      ) s
where rn = 1;

【讨论】:

  • rank() 在您的 SQL 中是什么意思? MySQL Workbench 告诉我有一个错误:o
  • 当我将光标悬停在您的 SQL 上时,MySQL 工作台显示“语法错误:发现无关输入 - 预期为‘右括号’”
  • 错误代码:1064。您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 3 行的 '() over(partition by user_id order by ctime desc) rn from your_table_nam' 附近使用正确的语法
【解决方案2】:

最简单的方法是:

select * 
from my_table t
where ctime = (select max(ctime) from my_table where user_id = t.user_id);

但是,如果user_id有多个相同的日期,您也可以在内部查询中使用limit子句

select * 
from my_table t
where id = (select id 
            from my_table 
            where  user_id = t.user_id
            order by ctime desc 
            LIMIT 1);

【讨论】:

  • 另外我不明白您所说的“user_id 的多个相同日期”是什么意思,您能解释一下吗?
猜你喜欢
  • 2020-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-01
  • 2012-06-02
  • 2012-02-12
  • 2012-04-10
相关资源
最近更新 更多