Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>I'm tracking views to different pages, and I want to know the highest page per session, in order to know how far they've clicked through (they're required to view every page all the way to the end) in any given session.</p> </blockquote> <p>Ordering before grouping is a highly unreliable way to do this.</p> <p><code>MySQL</code> extends <code>GROUP BY</code> syntax: you can use ungrouped and unaggregated fields in <code>SELECT</code> and <code>ORDER BY</code> clauses.</p> <p>In this case, a random value of <code>page</code> is output per each <code>session</code>.</p> <p><a href="http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html" rel="noreferrer"><strong>Documentation</strong></a> explicitly states that you should never make any assumptions on which value exactly will it be:</p> <blockquote> <p>Do not use this feature if the columns you omit from the <code>GROUP BY</code> part are not constant in the group. The server is free to return any value from the group, so the results are indeterminate unless all values are the same. </p> </blockquote> <p>However, in practice, the values from the first row scanned are returned.</p> <p>Since you are using an <code>ORDER BY page DESC</code> in your subquery, this row happens to be the rows with a maximal <code>page</code> per session.</p> <p>You shouldn't rely on it, since this behaviour is undocumented and if some other row will be returned in next version, it will not be considered a bug.</p> <p>But you don't even have to do such nasty tricks.</p> <p>Just use aggregate functions:</p> <pre><code>SELECT MAX(page) FROM views WHERE user_id = '1' GROUP BY session </code></pre> <p>This is documented and clean way to do what you want.</p> <p>Create a composite index on <code>(user_id, session, page)</code> for the query to run faster.</p> <p>If you need all columns from your table, not only the aggregated ones, use this syntax:</p> <pre><code>SELECT v.* FROM ( SELECT DISTINCT user_id, session FROM views ) vo JOIN views v ON v.id = ( SELECT id FROM views vi WHERE vi.user_id = vo.user_id AND vi.session = vo.session ORDER BY page DESC LIMIT 1 ) </code></pre> <p>This assumes that <code>id</code> is a <code>PRIMARY KEY</code> on <code>views</code>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload