Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

How do I find the second-highest distinct value with a subquery?

Quick answer

In SQLite, select distinct scores in a subquery, sort them from highest to lowest, then skip the first and take one. For example, with scores 100, 100, 92, and 85, the query returns 92. Filtering out NULL excludes missing scores from the values being ranked. If fewer than two eligible distinct scores exist, the query returns no row. [S1]

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

How do I get the second-highest distinct score in SQLite? I have a results table with a score column.

Geez

Select distinct scores in a subquery, sort them from highest to lowest, then use LIMIT 1 OFFSET 1 to return the second value:

SELECT score
FROM (
  SELECT DISTINCT score
  FROM results
  WHERE score IS NOT NULL
  ORDER BY score DESC
  LIMIT 1 OFFSET 1
);

The inner query removes duplicate scores before sorting and skipping the highest one. The outer query returns the remaining score as a result row. SQLite supports ordering results and limiting how many rows are returned; a SELECT enclosed in parentheses is a subquery. [S1] [S2] The WHERE condition explicitly excludes missing scores.

Follow-up question

What happens if two rows share the top score? For example, the scores are 100, 100, 92, and 85.

Geez

The query returns 92. DISTINCT reduces the values to 100, 92, and 85 before OFFSET 1 skips the highest value. Without DISTINCT, sorting the original rows and skipping one row would still leave a 100 at the top: the second row would also have the top score. That is why DISTINCT belongs in the inner query, before its ordering and limit are applied. [S1]

The distinct values, in order, are:

  1. 100
  2. 92
  3. 85

The query selects item 2.

Follow-up question

Why filter out NULL, and what if there aren’t two different scores?

Geez

The filter states that missing scores should not be included among the values being ranked. If score can be NULL, decide how you want those values handled; SQLite’s guidance notes that NULL handling should be considered. [S1]

With the filter shown, if there are fewer than two distinct non-NULL scores, the query returns no rows. [S1] If you instead use the subquery as a scalar expression, SQLite returns NULL when the inner SELECT has no row. [S2] Those are different result shapes: no result row versus one row whose value is NULL.

Follow-up question

Can you give me a copyable example and a small checklist to adapt it?

Geez

With the four example scores in the table, run the query above and expect one row containing 92. Replace results and score with your actual table and column names. The query selects values and does not change table contents.

Before relying on the result, check that the query matches your intended meaning:

  1. Confirm the column contains the values you want to rank.
  2. Keep DISTINCT if ties should count as one value.
  3. Use ORDER BY score DESC to rank highest first.
  4. Keep LIMIT 1 OFFSET 1 to skip one distinct value and take the next.
  5. Decide whether NULL scores should be excluded.
  6. Check whether fewer than two eligible distinct values is possible.

This query finds one overall second-highest distinct value; it does not calculate a separate result for each group.

A practical checklist

  • Confirm the table and column names.

  • Keep DISTINCT so tied scores count once.

  • Sort descending to put the highest value first.

  • Use LIMIT 1 OFFSET 1 to select the next distinct value.

  • Decide whether NULL scores should be excluded.

  • Consider what to do when there is no second value.

A few more useful answers

Does this return every row tied for second place?

No. It returns the second-highest distinct score value once. To retrieve original rows with that value, use a separate query that filters rows by the value returned here.

What does the query return if there is only one distinct non-NULL score?

With the shown filter, the inner query has no second value, so the outer query returns no rows. A scalar-subquery form instead returns one row with a NULL value when its inner query returns no rows. [S2]

Sources

References used for this guide.

  1. [S1] SQLite SELECT: sorting and limiting query results
    sqlite.org · Checked
  2. [S2] SQLite SQL Language Expressions: subquery expressions
    sqlite.org · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work