Sql MAX()作为左联接的筛选子句,是否有其他选择?

Sql MAX()作为左联接的筛选子句,是否有其他选择?,sql,sqlite,max,left-join,Sql,Sqlite,Max,Left Join,在我看来,这个查询还有另一个选项,但我无法准确指出该选项是什么: @Query("" + "SELECT " + "... not really important... " + "FROM (" + "SELECT ect.* " + "FROM element_constant_table ect &qu

在我看来,这个查询还有另一个选项,但我无法准确指出该选项是什么:

@Query("" +
        "SELECT " +
        "... not really important... " +
        "FROM (" +
        "SELECT ect.* " +
        "FROM element_constant_table ect " +
        "WHERE book_parent_id = :bookId AND availability = 1" +
        ") ect1 " +
        "LEFT JOIN " +
        "element_version_table evt " +
        "ON (" +
            "SELECT evt.element_parent_id " +
            "WHERE " +
            "evt.time = (" +
                "SELECT MAX(evt2.time) " +
                "FROM element_version_table evt2 " +
                "WHERE evt2.element_parent_id = evt.element_parent_id" +
            ") " +
        ") = ect1.element_id" +
        "")
public abstract LiveData<List<Element>> getLatestElementsAt(int bookId);
MAX()函数强制对
元素常量表
中的每一行执行整个
元素版本表
的新实例化

我知道可能会发生类似的情况,所以我总是在表到达左联接之前尝试对其进行筛选,在本例中使用子句
“WHERE book\u parent\u id=:bookId AND availability=1”

在on子句之前,无法过滤左表并使其与右表上相应的键一致,因此需要将WHERE放在那里

问题是,如果不使用MAX(),而是在ON子句中使用简单的ORDER BY evt.time DESC LIMIT 1,编译器会告诉我没有evt.time字段(我假设它还不存在)。 因此,我的结论是:

a)ORDER BY要求将表实例化为其完整长度(在行定位过程中不会发生)。

b)ON子句发生在左表的实例化(我假设是)达到其完整长度之前。

我关于条款执行顺序的结论正确吗

这个查询在一个庞大的数据库上会有多大的负担?和
更好的选择是什么?

请使用下面的sql查询在代码中检索书籍的实时数据:

     SELECT 
    ... not really important... 
    FROM element_constant_table ect 
    LEFT JOIN 
    (SELECT evt.*, ROW_NUMBER() OVER (PARTITION BY evt.element_parent_id ORDER BY evt.time DESC) as seqnum 
    from element_version_table evt) evt_final on ect.element_id = evt_final.element_parent_id and evt_final.seqnum=1
    where ect.book_parent_id = :bookId AND ect.availability = 1

我在这里找到“element\u version\u table”(如果存在)中的最新图书记录。

SQLite窗口函数ROW\u NUMBER()可以解决您的问题

您没有提供表的全部详细信息。但是,根据element_版本表的大小和查询性能,您可以尝试:

SELECT 
    ... not really important...  FROM
    (SELECT ect.*
    FROM element_constant_table ect
    WHERE book_parent_id=:bookId AND availability=1
    ) ect1

    LEFT JOIN

    (SELECT t.*
     FROM
        (SELECT
            evt.*,
            ROW_NUMBER() OVER (PARTITION BY element_parent_id ORDER BY evt.time DESC) rn
         FROM element_version_table evt) t
     WHERE t.rn = 1
    ) evt1

    ON ect1.element_id = evt1.element_parent_id

此解决方案适用于SQLite版本<3.25.0 感谢用户@armamut提出了最初的想法和7年前的另一个问题


选择evt.element\u parent\u id WHERE…
FROM子句在哪里?是的,我有同样的疑问,但查询实际上是有效的,该表来自一个被称为“element\u version\u table evt”的表。。。。哦,这就是为什么找不到evt.time的原因吗???也许它可以工作,但您的查询不可读。发布示例数据和预期结果,以澄清您想要的内容。嘿,感谢您的回答,我相信这是可行的,但解决方案适用于SQLite版本,从3.25.0开始,以及超过3.25.0的版本,我的版本为3.19,但行数=1非常聪明,因为它避免了在关联之前裁剪表。分区方式是一种分组方式,这意味着你在有效地过滤左边的表,给你一个最上面的元素,以及每个按时间排序的组,我认为在3.19中没有办法做到这一点。在比赛开始之前。谢谢你的回答
SELECT 
    ... not really important...  FROM
    (SELECT ect.*
    FROM element_constant_table ect
    WHERE book_parent_id=:bookId AND availability=1
    ) ect1

    LEFT JOIN

    (SELECT t.*
     FROM
        (SELECT
            evt.*,
            ROW_NUMBER() OVER (PARTITION BY element_parent_id ORDER BY evt.time DESC) rn
         FROM element_version_table evt) t
     WHERE t.rn = 1
    ) evt1

    ON ect1.element_id = evt1.element_parent_id
SELECT t.*
FROM
    (SELECT 
        ... not really important...,
        ROW_NUMBER() OVER (PARTITION BY ect1.element_id, evt1.element_parent_id ORDER BY evt1.time DESC) rn

    FROM
        (SELECT ect.*
        FROM element_constant_table ect
        WHERE book_parent_id=:bookId AND availability=1
        ) ect1

        LEFT JOIN element_version_table evt1
        ON ect1.element_id = evt1.element_parent_id
    ) t
WHERE t.rn = 1
@Query("" +
        "SELECT " +
        ... not really important ...
        "FROM (" +
            "SELECT ect.* " +
            "FROM element_constant_table ect " +
            "WHERE book_parent_id = :bookId AND availability = 1" +
        ") ect1 " +
        "LEFT JOIN " +
        "(" +
            "SELECT " +
                "evt.*," +
                "MAX(evt.time) " +
            "FROM element_version_table evt " +
            "GROUP BY evt.element_parent_id" +
        ") evt1 " +
        "ON evt1.element_parent_id = ect1.element_id" +
        "")
public abstract LiveData<List<Element>> getLatestElementsAt(int bookId);
        SELECT 
        ... not really important ...
        FROM (
            SELECT ect.* 
            FROM element_constant_table ect 
            WHERE book_parent_id = :bookId AND availability = 1
        ) ect1 
        LEFT JOIN 
        (
            SELECT 
                evt.*,
                MAX(evt.time) 
            FROM element_version_table evt 
            GROUP BY evt.element_parent_id
        ) evt1 
        ON evt1.element_parent_id = ect1.element_id