【问题标题】:GROUP BY also SELECT non-constant columnsGROUP BY 还 SELECT 非常量列
【发布时间】:2012-10-23 08:52:53
【问题描述】:

我的数据库中有 2 个表:

log_visitors:
--------------------
id | host_id


log_access:
--------------------
visitor | document | timestamp

log_access.visitor 链接到log_visitors.id

目前,我正在使用这个查询:

SELECT
    log_visitors.host_id
    , MIM(log_access.timestamp) AS min_timestamp
FROM
    log_access
    INNER JOIN log_visitors
        ON (log_access.visitor = log_visitors.id)
GROUP BY log_visitors.host_id;

为数据库中的每个host_id 获取MIN(timestamp)

这是我的问题:

我还需要使用该时间戳获取 document 进行访问...我不能简单地将log_access.document 添加到 SELECT 列表中,因为它不是恒定的而且我没有按文档分组... 有什么想法吗?

【问题讨论】:

    标签: mysql sql select group-by greatest-n-per-group


    【解决方案1】:

    您没有指定您的 DBMS,但这是 ANSI SQL(适用于大多数现代 DBMS)

    select *
    from (
      SELECT log_visitors.host_id,
             log_visitors.document,
             log_access.timestamp
             min(log_access.timestamp) OVER (partition by log_visitors.host_id) AS min_timestamp
      FROM log_access
        JOIN log_visitors ON (log_access.visitor = log_visitors.id)
    ) t
    where t.timestamp = t.min_timestamp
    ORDER BY host_id
    

    【讨论】:

    • 子查询不需要GROUP BY吗?
    • @ypercube:不,它没有。这就是窗口函数的用途。
    • @dash:请取消删除您的答案。原因之一是某些 DBMS(如 MySQL)没有窗口函数。第二个是您的查询在某些情况下甚至可能表现更好(或者使用不成熟的优化器)。
    • @ypercube 已经完成了——不过,在这些情况下,我从来没有真正确定过礼仪。感谢您的建议。
    【解决方案2】:

    类似以下的内容应该可以满足您的需求:

    SELECT      lv.host_id,
                mv.MinTime,
                la.document
    
    FROM        log_visitors AS lv
    INNER JOIN     
                (SELECT visitor, 
                        MIN(timestamp) AS MinTime 
                 FROM log_access 
                 GROUP BY visitor) AS mv ON lv.id = mv.visitor
    INNER JOIN  log_access AS la ON lv.id = la.visitor AND mv.MinTime = la.timestamp
    

    我们所做的是获取所有访问者的列表和表中的最小时间戳,加入该列表,然后重新加入时间戳上的日志访问以选择特定文档。

    这使用 ANSI SQL-92,因此应该适用于广泛的数据库系统,包括那些不支持窗口函数的系统。

    这是一个通过Sql Fiddle进行的查询示例

    【讨论】:

    • 谢谢,这真的很有帮助!我的服务器是 MySQL(OVER/PARTITION BY 不起作用)。现在我试图弄清楚,如何获得具有适当文档编号的 MAX(时间戳)(所以我的结果表有“MinTime,MaxTime,MinDocument,MaxDocument,id”之类的列。找到了一个再加入的解决方案,但是看起来太费力了……
    • @MichalKosek 一个额外的连接听起来很合适,所以不用担心!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    相关资源
    最近更新 更多