How to select distinct based on condition (another column) [duplicate] - mysql

This question already has answers here:
Fetch the rows which have the Max value for a column for each distinct value of another column
(35 answers)
Closed last year.
I am trying to select distinct values from a table based on date column. I mean I want to extract the distinct rows with higher value of date column
ID| house | people| date
------------------------------
1 | a | 5 | 2021-10-20
2 | a | 5 | 2022-01-20
3 | b | 4 | 2021-10-20
4 | b | 4 | 2022-01-20
After query is runned, I want the below result:
a | 5 | 2022-01-20
b | 4 | 2022-01-20
I have tried below query but I have no idea how to add the condition (show the distinct row with higher date value.
SELECT DISTINCT house, people FROM Table
I tried SELECT DISTINCT house, people FROM Table WHERE MAX(date) but got some errors.
Any ideas?

You can get the row number for each row partitoned by house and ordered by date desc. then only select the rows with row number = 1:
select house, people, date
from(select house, people, date, row_number() over(partition by house order by date desc) rn
from table_name) t
where rn = 1
Fiddle

You will need aggregation via group by and the max date, filtering out rows that are older to 1) ensure that your grouping occurs faster and 2) ignore items that have no newer date values.
SELECT house, people, max(`date`)
FROM Table
WHERE `date` > '2021-10-20 00:00:00'
GROUP BY house, people

Related

Limit MySQL Results to One From Each "Group"

Suppose we have a table like the one below.
Id | Name | Group
-----------------
1 | John | 1
2 | Zayn | 2
3 | Four | 2
4 | Ben_ | 3
5 | Joe_ | 2
6 | Anna | 1
The query below will select all of them.
SELECT `Name` FROM `Table` WHERE 1;
How would I select only one person from each group? Who it is doesn't really matter, as long as there's only one name from group 1 and one name from group 2 etc.
The GROUP BY clause isn't fit for this (according to my error console) because I am selecting non aggregated values, which makes sense.
The DISTINCT clause isn't great here either, since I don't want to select the "Group" and definitely not group by their names.
If is not important the resulting name You can anawy leverage some group functions eg with max or min..
leverage the group functions
select max(name) from your_table
group by Group;
otherwise you can use subquery
select name from your_table
where Id in (select min(Id) from your_table group by Group);

Query to Find Duplicate entries

I am looking for an SQL query to give me a list of duplicate entries in a table. However, there are 3 different columns to take into account. First is an ID, Second is a Name, and third is a Date. The situation is that there are multiple Names that are assigned with the same ID, and there are multiple records of those in a day, which makes THOUSANDS of different records per day.
I already filtered it so that only results for the past 7 days will show, but the amount of records is still too much for me to extract. I just want to decrease the number of rows in the output order to properly extract the results.
Sample
|--id-|--name--|-------date------|
| 1 | a |5-9-2015, 10:00am|
| 1 | a |5-8-2015, 10:02am|
| 1 | a |5-8-2015, 11:00am|
| 1 | b |5-8-2015, 10:00am|
| 1 | b |5-8-2015, 10:02am|
| 1 | c |5-8-2015, 10:00am|
| 2 | d |5-8-2015, 10:00am|
expected output
|--id-|--name--|
| 1 | a |
| 1 | b |
| 1 | c |
| 2 | d |
Inclusion of entries without any duplicates are fine. The important thing is to only return a single record of a unique id-name combination for a day.
Thanks in advance for any help that you can give.
You can get the combinations as:
select distinct id, name
from sample;
If you want duplicates, using group by and having:
select id, name
from sample
group by id, name
having count(*) > 1;
EDIT:
If you want this by date, then add date(date) to the group by and perhaps select clauses.
To return single id-name data per day you can use this:
select id, name
from tab
group by id, name, date(date)
The DATE() function extracts the date part of a date or date/time expression.
select id,name
from sample
group by id,name,DATE(date)
having count(*)>1;

Select distinct values from query excluding sorting-purpose column

Description:
I want to select my site content's categories. Most of them will be created by users so I will ve to deal with problem of many categories in table. I want to respect some kind content's trends on my site. My solution is:
Select all categories from past 2 days and sort it by number of appearances (ascending),
Union query (distinct)
Select all categories from date < past 2 days and sort it like above.
Thanks to it I ve all most popular categories from small amount of time + most popular categories in global scope.
Query:
(SELECT category, COUNT(*) AS number FROM data WHERE date BETWEEN ADDDATE(NOW(), INTERVAL -2 DAY) AND NOW() GROUP BY category)
UNION
(SELECT category, COUNT(*) AS number FROM data WHERE date < ADDDATE(NOW(), INTERVAL -2 DAY) GROUP BY category)
ORDER BY number DESC LIMIT 50
Output:
+----------+--------+
| category | number |
+----------+--------+
| 2 | 3 |
| 4 | 3 |
| 6 | 3 |
| 5 | 2 |
| 1 | 2 |
| 2 | 1 |
+----------+--------+
6 rows in set (0.00 sec)
Note there is duplicated content in category (id 2), UNION DISTINCT (default) is not excluding this because it compares rows from both columns, so:
+----------+--------+
| category | number |
+----------+--------+
| 2 | 3 | //is not equal to
| 2 | 1 | //below values
+----------+--------+
//wont be excluded
Problem to slove:
I need to select distinct values from only category column.
(number is only for sorting purposes and used only in this query)
If I understand your question correctly, this should be the query that you need:
SELECT category
FROM (
SELECT category, COUNT(*) AS number
FROM data WHERE date BETWEEN ADDDATE(NOW(), INTERVAL -2 DAY) AND NOW()
GROUP BY category
UNION ALL
SELECT category, COUNT(*) AS number
FROM data WHERE date < ADDDATE(NOW(), INTERVAL -2 DAY)
GROUP BY category
ORDER BY number DESC
) s
GROUP BY category
ORDER BY MAX(number) DESC
LIMIT 50
I removed brackets () around your two queries that make your union query because the ORDER BY of your UNION query will be applied to both. I also used UNION ALL instead of UNION because categories are grouped again in the outer query, i would try both UNION/UNION ALL to see which one is faster.
Then I'm grouping again, by category, and ordering by the MAX(number) of your category, and keeping only the first 50 rows.

ORDER BY on multiple conditions

I need a query that will give me the result that is either (a) the highest price or (b) the one with the oldest timestamp. In all cases, price should trump timestamp (ie if a record has a really old timestamp by higher price than all others, it should always return the record with the highest price)
Here are a few scenarios:
id | price | date
1 | 5 | 2012-02-20 08:59:06
2 | 5 | 2012-02-20 09:59:06
3 | 7 | 2012-02-20 10:59:06
Should return id 3 because it is highest price
id | price | date
1 | 5 | 2012-02-20 08:59:06
2 | 5 | 2012-02-20 09:59:06
3 | 5 | 2012-02-20 10:59:06
should return id 1 since it is the oldest
In my current query i am doing this:
SELECT * FROM table ORDER BY price, date DESC LIMIT 1
Unfortunately this query is not working how i've outlined it above.
Thanks for your help
I'm having trouble determining precisely what you are after, however it sounds like you are looking for the oldest timestamp for the highest price, and so the following should suffice
SELECT *
FROM table
ORDER BY
price DESC, // Favour the highest price
date ASC // Now get the one with oldest date at this price
LIMIT 1
i hope i understand your question, try this
SELECT
p.*
FROM table p
WHERE price = (SELECT MAX(price) FROM table)
OR date = (SELECT MIN(date) FROM table)

Mysql multi count in one query

How can I count records for two columns in one table using different query criteria?
Table looks like:
user_id | date | status
------------------------------
1 | 2011-01-02 | 1
2 | 2011-01-03 | 1
3 | 2011-01-02 | 0
4 | 2011-01-03 | 1
1 | 2011-01-02 | 1
I want to count two values in one query. The first one is number of user_id group by status and the second is count of user_id group by date.
How can I do that?
You can't have different GROUP BY clauses in the same query -- each count will have to be in an independent query.
But you can return the output in a single query/resultset using subselects (subquery in the SELECT clause):
SELECT COUNT(a.user_id) AS numUsersPerStatus,
(SELECT COUNT(b.user_id)
FROM YOUR_TABLE b
GROUP BY b.date) AS numUsersPerDate
FROM YOUR_TABLE a
GROUP BY a.status
You don't.
You should use two queries. There's no advantage to doing this with a single query.
If you really want to do it you can try this:
SELECT 'date' AS grptype, date AS grp, COUNT(DISTINCT user_id) AS cnt
FROM yourtable
GROUP BY date
UNION ALL
SELECT 'status' AS grptype, status AS grp, COUNT(DISTINCT user_id) AS cnt
FROM yourtable
GROUP BY status
Result:
grptype grp cnt
date 2011-01-02 2
date 2011-01-03 2
status 0 1
status 1 3
However I would strongly advise against doing this. You want two different and unrelated result sets so you should use two separate queries.