Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 785 Vote(s) - 3.55 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How can I SELECT rows with MAX(Column value), PARTITION by another column in MYSQL?

#11
You can also try this one and for large tables query performance will be better. It works when there no more than two records for each home and their dates are different. Better general MySQL query is one from Michael La Voie above.

SELECT t1.id, t1.home, t1.date, t1.player, t1.resource
FROM t_scores_1 t1
INNER JOIN t_scores_1 t2
ON t1.home = t2.home
WHERE t1.date > t2.date

Or in case of Postgres or those dbs that provide analytic functions try

SELECT t.* FROM
(SELECT t1.id, t1.home, t1.date, t1.player, t1.resource
, row_number() over (partition by t1.home order by t1.date desc) rw
FROM topten t1
INNER JOIN topten t2
ON t1.home = t2.home
WHERE t1.date > t2.date
) t
WHERE t.rw = 1

Reply

#12
Why not using:
SELECT home, MAX(datetime) AS MaxDateTime,player,resource FROM topten GROUP BY home
Did I miss something?
Reply

#13
I think this will give you the desired result:

SELECT home, MAX(datetime)
FROM my_table
GROUP BY home


**BUT** if you need other columns as well, just make a join with the original table (check `Michael La Voie` answer)

Best regards.
Reply

#14
this is the query you need:

SELECT b.id, a.home,b.[datetime],b.player,a.resource FROM
(SELECT home,MAX(resource) AS resource FROM tbl_1 GROUP BY home) AS a

LEFT JOIN

(SELECT id,home,[datetime],player,resource FROM tbl_1) AS b
ON a.resource = b.resource WHERE a.home =b.home;

Reply

#15
@Michae The accepted answer will working fine in most of the cases but it fail for one for as below.

In case if there were 2 rows having HomeID and Datetime same the query will return both rows, not distinct HomeID as required, for that add Distinct in query as below.

SELECT DISTINCT tt.home , tt.MaxDateTime
FROM topten tt
INNER JOIN
(SELECT home, MAX(datetime) AS MaxDateTime
FROM topten
GROUP BY home) groupedtt
ON tt.home = groupedtt.home
AND tt.datetime = groupedtt.MaxDateTime

Reply

#16
Another way to gt the most recent row per group using a sub query which basically calculates a rank for each row per group and then filter out your most recent rows as with rank = 1

select a.*
from topten a
where (
select count(*)
from topten b
where a.home = b.home
and a.`datetime` < b.`datetime`
) +1 = 1

[DEMO][1]

Here is the [visual demo][2] for rank no for each row for better understanding

> By reading some comments **what about if there are two rows which have same 'home' and 'datetime' field values?**

Above query will fail and will return more than 1 rows for above situation. To cover up this situation there will be a need of another criteria/parameter/column to decide which row should be taken which falls in above situation. By viewing sample data set i assume there is a primary key column `id` which should be set to auto increment. So we can use this column to pick the most recent row by tweaking same query with the help of `CASE` statement like

select a.*
from topten a
where (
select count(*)
from topten b
where a.home = b.home
and case
when a.`datetime` = b.`datetime`
then a.id < b.id
else a.`datetime` < b.`datetime`
end
) + 1 = 1

[DEMO][3]

Above query will pick the row with highest id among the same `datetime` values

[visual demo][4] for rank no for each row


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

[4]:

[To see links please register here]

Reply

#17
You are so close! All you need to do is select BOTH the home and its max date time, then join back to the `topten` table on BOTH fields:


SELECT tt.*
FROM topten tt
INNER JOIN
(SELECT home, MAX(datetime) AS MaxDateTime
FROM topten
GROUP BY home) groupedtt
ON tt.home = groupedtt.home
AND tt.datetime = groupedtt.MaxDateTime

Reply

#18
The fastest `MySQL` solution, without inner queries and without `GROUP BY`:

SELECT m.* -- get the row that contains the max value
FROM topten m -- "m" from "max"
LEFT JOIN topten b -- "b" from "bigger"
ON m.home = b.home -- match "max" row with "bigger" row by `home`
AND m.datetime < b.datetime -- want "bigger" than "max"
WHERE b.datetime IS NULL -- keep only if there is no bigger than max


**Explanation**:

Join the table with itself using the `home` column. The use of `LEFT JOIN` ensures all the rows from table `m` appear in the result set. Those that don't have a match in table `b` will have `NULL`s for the columns of `b`.

The other condition on the `JOIN` asks to match only the rows from `b` that have bigger value on the `datetime` column than the row from `m`.

Using the data posted in the question, the `LEFT JOIN` will produce this pairs:


+------------------------------------------+--------------------------------+
| the row from `m` | the matching row from `b` |
|------------------------------------------|--------------------------------|
| id home datetime player resource | id home datetime ... |
|----|-----|------------|--------|---------|------|------|------------|-----|
| 1 | 10 | 04/03/2009 | john | 399 | NULL | NULL | NULL | ... | *
| 2 | 11 | 04/03/2009 | juliet | 244 | NULL | NULL | NULL | ... | *
| 5 | 12 | 04/03/2009 | borat | 555 | NULL | NULL | NULL | ... | *
| 3 | 10 | 03/03/2009 | john | 300 | 1 | 10 | 04/03/2009 | ... |
| 4 | 11 | 03/03/2009 | juliet | 200 | 2 | 11 | 04/03/2009 | ... |
| 6 | 12 | 03/03/2009 | borat | 500 | 5 | 12 | 04/03/2009 | ... |
| 7 | 13 | 24/12/2008 | borat | 600 | 8 | 13 | 01/01/2009 | ... |
| 8 | 13 | 01/01/2009 | borat | 700 | NULL | NULL | NULL | ... | *
+------------------------------------------+--------------------------------+


Finally, the `WHERE` clause keeps only the pairs that have `NULL`s in the columns of `b` (they are marked with `*` in the table above); this means, due to the second condition from the `JOIN` clause, the row selected from `m` has the biggest value in column `datetime`.


Read the [SQL Antipatterns: Avoiding the Pitfalls of Database Programming][1] book for other SQL tips.


[1]:

[To see links please register here]

Reply

#19
Hope below query will give the desired output:
```sql
Select id, home,datetime,player,resource, row_number() over (Partition by home ORDER by datetime desc) as rownum from tablename where rownum=1
```
Reply

#20
*(NOTE: The answer of Michael is perfect for a situation where the target column `datetime` cannot have duplicate values for each distinct `home`.)*

If your table has **duplicate rows for `home`x`datetime` and you need to only select one row for each distinct `home` column**, here is my solution to it:

Your table needs one unique column (like `id`). If it doesn't, create a view and add a random column to it.

Use this query to select a single row for each unique `home` value. Selects the lowest `id` in case of duplicate `datetime`.


SELECT tt.*
FROM topten tt
INNER JOIN
(
SELECT min(id) as min_id, home from topten tt2
INNER JOIN
(
SELECT home, MAX(datetime) AS MaxDateTime
FROM topten
GROUP BY home) groupedtt2
ON tt2.home = groupedtt2.home
) as groupedtt
ON tt.id = groupedtt.id

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through