Home > Software design >  How to select different corresponding column while using max and group by
How to select different corresponding column while using max and group by

Time:08-19

maybe simple question but I have this table:

 ---- ---------- ------------- ------------------ --------------------- --------- 
| id | realtyId | priceTypeId | price            | date                | comment |
 ---- ---------- ------------- ------------------ --------------------- --------- 
|  1 |        1 |           1 |     7.1100000000 | 2022-07-16 20:51:47 | []      |
|  2 |        2 |           1 |     2.3400000000 | 2022-07-16 21:01:05 | []      |
|  3 |        2 |           2 | 23950.0000000000 | 2022-07-16 21:03:58 | []      |
|  4 |        4 |           1 |     6.1800000000 | 2022-07-16 21:27:59 | []      |
|  5 |        5 |           1 |     6.1800000000 | 2022-07-16 21:28:12 | []      |
|  6 |        6 |           1 |     6.1800000000 | 2022-07-16 21:28:23 | []      |
|  7 |        7 |           1 |     3.9200000000 | 2022-07-16 21:28:37 | []      |
|  8 |       10 |           1 |     3.4500000000 | 2022-07-16 22:01:05 | []      |
|  9 |       11 |           1 |     4.6600000000 | 2022-07-16 22:15:37 | []      |
| 10 |       16 |           1 |     4.2400000000 | 2022-07-16 22:23:25 | []      |
| 11 |       10 |           4 | 45000.0000000000 | 2022-07-16 22:28:22 | []      |
| 12 |       16 |           4 | 45000.0000000000 | 2022-07-16 22:35:40 | []      |
| 13 |        6 |           4 | 25000.0000000000 | 2022-07-16 22:37:27 | []      |
| 14 |       16 |           4 |  4633.0000000000 | 2022-07-31 16:56:33 | []      |
| 15 |        7 |           4 | 25584.0000000000 | 2022-07-31 16:57:11 | []      |
| 16 |        4 |           4 |  8485.0000000000 | 2022-07-31 18:32:36 | []      |
 ---- ---------- ------------- ------------------ --------------------- --------- 

I need to get the price of the highest priceTypeId for a realtyId. While I try this:

select id,realtyId,max(priceTypeId),price from prices group by realtyId

I get

 ---- ---------- ------------------ -------------- 
| id | realtyId | max(priceTypeId) | price        |
 ---- ---------- ------------------ -------------- 
|  1 |        1 |                1 | 7.1100000000 |
|  2 |        2 |                2 | 2.3400000000 |
|  4 |        4 |                4 | 6.1800000000 |
|  5 |        5 |                1 | 6.1800000000 |
|  6 |        6 |                4 | 6.1800000000 |
|  7 |        7 |                4 | 3.9200000000 |
|  8 |       10 |                4 | 3.4500000000 |
|  9 |       11 |                1 | 4.6600000000 |
| 10 |       16 |                4 | 4.2400000000 |
 ---- ---------- ------------------ -------------- 

But I need to get the corresponding price for the max of priceTypeId (for example id 2 should be 23950)

Also. if there are two or more priceTypeIds with the same number for the same realtyId, it should take the latest one (thats the purpose of date column)

Thank you if U can help me

CodePudding user response:

You either aggregate a column in your SELECT clause with an aggregation formula or you include that column in your GROUP BY clause. By adding price to your SELECT clause and not aggregating it via formula or putting it in your GROUP BY clause, you are telling mysql "If there are multiple prices for this GROUP BY, I don't care which one you pick, surprise me". Newer versions of mysql error out with SQL like this, as does every other RDBMS. This "feature" of mysql has led many people to misunderstand what GROUP BY is doing, what its limitations are, and how to use it properly.

At any rate, a correlated subquery will solve your requirements:

SELECT id,realtyId, priceTypeID ,price 
FROM prices p1
WHERE priceTypeID = 
   (
       SELECT max(priceTypeID) 
       FROM prices p2
       WHERE p1.id = p2.id
          AND p1.realtyID = p2.realtyID
   )

CodePudding user response:

First thing you'll need is the highest priceTypeId by realtyId.

SELECT realtyId, max(priceTypeId) AS priceTypeId
  FROM prices
 GROUP BY realtyId;

With that you could select all matching prices:

WITH maxTypeIds AS (
  SELECT realtyId, max(priceTypeId) AS priceTypeId
    FROM prices
   GROUP BY realtyId
)
SELECT * FROM prices 
 INNER JOIN maxTypeIds USING (realtyId, priceTypeId);

Now, it could happen, that there are multiple prices (different ids) having the same priceTypeId, in that case, you want to have the most recent one. One can do the same thing again, but with max(date) instead of max(priceTypeId):

WITH maxTypeIds AS (
  SELECT realtyId, max(priceTypeId) AS priceTypeId
    FROM prices
   GROUP BY realtyId
), maxPrices AS (
  SELECT * FROM prices 
   INNER JOIN maxTypeIds USING (realtyId, priceTypeId)
), lastPrices AS (
  SELECT realtyId, max(date) AS date 
    FROM maxPrices
   GROUP BY realtyId
)    
SELECT maxPrices.* FROM maxPrices
 INNER JOIN lastPrices USING (realtyId, date);

results in

realtyId priceTypeId id price date comment
1 1 1 7.1100000000 2022-07-16 20:51:47 []
2 2 3 23950.0000000000 2022-07-16 21:03:58 []
5 1 5 6.1800000000 2022-07-16 21:28:12 []
11 1 9 4.6600000000 2022-07-16 22:15:37 []
10 4 11 45000.0000000000 2022-07-16 22:28:22 []
6 4 13 25000.0000000000 2022-07-16 22:37:27 []
16 4 14 4633.0000000000 2022-07-31 16:56:33 []
7 4 15 25584.0000000000 2022-07-31 16:57:11 []
4 4 16 8485.0000000000 2022-07-31 18:32:36 []
  • Related