ryyst
ryyst

Reputation: 9799

SQL - selecting all rows with maximum value

I have this SQL query:

SELECT id, COUNT(*) AS price
FROM (SELECT * FROM rt WHERE somecondition) AS st
      JOIN tt
      ON st.id = tt.id
GROUP BY id;

Now, I want to select all rows which have the maximum price of the table. I have tried this, which unfortunately returns no row at all:

SELECT id, COUNT(*) AS price
FROM (SELECT * FROM rt WHERE somecondition) AS st
      JOIN tt
      ON st.id = tt.id
GROUP BY id
HAVING price = MAX(price);

I'm somewhat lost, does anybody have any pointers?

Upvotes: 8

Views: 9096

Answers (6)

user970780
user970780

Reputation: 71

This looks fairly simple to me:

select * from <table> 
where <column name> in(
   SELECT MAX(column name) FROM table
)

Upvotes: 4

Zane Bien
Zane Bien

Reputation: 23135

Try this solution:

SELECT a.id, a.price
FROM
(
    SELECT aa.id, COUNT(1) AS price
    FROM rt aa
    INNER JOIN tt bb ON aa.id = bb.id
    WHERE aa.somecondition
    GROUP BY aa.id
) a
INNER JOIN
(
    SELECT MAX(aa.price) AS maxprice
    FROM
    (
        SELECT COUNT(1) AS price
        FROM rt aaa
        INNER JOIN tt bbb ON aaa.id = bbb.id
        WHERE aaa.somecondition
        GROUP BY aaa.id
    ) aa
) b ON a.price = b.maxprice

Edit: While I can't think of any way to rewrite this so as to not have to write the base-queries redundantly, what you could perhaps do is this:

SELECT GROUP_CONCAT(a.id) AS ids, a.price
FROM
(
    SELECT aa.id, COUNT(1) AS price
    FROM rt aa
    INNER JOIN tt bb ON aa.id = bb.id
    WHERE aa.somecondition
    GROUP BY aa.id
) a
GROUP BY a.price
ORDER BY a.price DESC
LIMIT 1

This produces a comma-separated-list of the ids that share the same maximum value. This is probably not the format you are looking for though, but it is one way to avoid having to write the base-query twice. Just putting that out there.

Upvotes: 1

shawnt00
shawnt00

Reputation: 17953

You asked for an approach that didn't require the redundancy of stating the inner query more than once. That's certainly what a cte is good for. These are two other solutions rewritten to use that tactic.

WITH basequery as (
    SELECT aa.id, COUNT(1) AS price
    FROM rt aa INNER JOIN tt bb ON aa.id = bb.id
    WHERE [aa.somecondition]
    GROUP BY aa.id
)
SELECT a.id, a.price
FROM
    basequery as a INNER JOIN
    (SELECT MAX(price) AS maxprice FROM basequery) as b
        ON a.price = b.maxprice
-- or
WITH basequery as (
    SELECT aa.id, COUNT(1) AS price
    FROM rt aa INNER JOIN tt bb ON aa.id = bb.id
    WHERE [aa.somecondition]
    GROUP BY aa.id
)
SELECT a.id, a.price
FROM
    basequery as a
WHERE
    a.price >= ALL (SELECT price FROM basequery)

Upvotes: 0

Nikson Kanti Paul
Nikson Kanti Paul

Reputation: 3440

HAVING is used to check conditions after the aggregation takes place.

WHERE is used before the aggregation takes place.

SELECT id, COUNT(*) AS price
FROM (SELECT * FROM rt WHERE somecondition) AS st
  JOIN tt
  ON st.id = tt.id
WHERE price = (SELECT MAX(price) FROM ...table)
GROUP BY id

Upvotes: 0

shawnt00
shawnt00

Reputation: 17953

Assuming that @Zane's answer is what you do want, here's a portable version of his query that also avoids LIMIT/TOP operations. I'm not really familiar with mysql dialects, but I imagine this will work without problem.

SELECT a.id, a.price
FROM (
    SELECT aa.id, COUNT(1) AS price
    FROM rt aa
    INNER JOIN tt bb ON aa.id = bb.id
    WHERE [somecondition]
    GROUP BY aa.id
) a
WHERE
    a.price >= ALL (
        SELECT COUNT(1) AS maxprice
        FROM rt aa
        INNER JOIN tt bb ON aa.id = bb.id
        WHERE [somecondition]
        GROUP BY aa.id
    )

Upvotes: 0

albanx
albanx

Reputation: 6343

try this, put MAX in select, this should be the correct way

SELECT id, COUNT(*) AS price, MAX(price) AS max_price
FROM (SELECT some_table_name FROM rt WHERE somecondition LIMIT 1) AS st
      JOIN thenextTable as tt
      ON st.id = tt.id
GROUP BY id;

Upvotes: 0

Related Questions