SQL query to select only the maximum items? - php

I have this table: I want to search by UID
ID | VID | UID
1 | 1 | 5
1 | 1 | 6
1 | 2 | 6
2 | 3 | 5
2 | 3 | 6
2 | 4 | 6
I want to end up with this result:
ID | VID | UID
1 | 2 | 6
2 | 4 | 6
In other words, only select the entries where the VID is MAX of the UID but keeping in min NID could differ. Something like this I suppose:
select * from TABLE where uid = 6 and max(vid)
???
But this doesn't work?

One way is to order by the value in descending order (so the max is at the top), then just select the first result.
SELECT t.ID,
t.VID,
t.UID
FROM table t
WHERE t.ID = 1
ORDER BY t.VID DESC
LIMIT 1
Or do you mean you want all rows where t.VID is the highest value? In which case you could do something like this,
SELECT t.ID,
t.VID,
t.UID
FROM table t
WHERE t.ID = 1
AND t.VID = (SELECT MAX(VID) FROM table);
EDIT: Based on the edit to your question, it looks like you just want the max VID value for each ID? If I'm understanding you correctly, then this should give you what you need.
SELECT t.ID,
max(t.VID) as VID,
t.UID
FROM table t
WHERE t.UID = 6
GROUP BY t.ID

You need to have a subquery. This should work:
select * from TABLE where ID='1' AND VID=(select max(VID) from TABLE)

I expect your real-life example is more complicated (at least has more data).
This query will give you the row you want.
SELECT id,vid, uid
FROM TABLE
where id = 1
and vid in (select max(vid) from TABLE where id = 1)

Related

Select the rows with lowest value in specific column from those who match the other critarias

I have created an SQL table to save events data into it.
Each event can have multiple occurrences and when I filter them on site - I want to have the first matching occurrence of each event. each occurrence is saved in a different row, which contains a column for the general event_id and specific occ_id to each occurrence.
I need to get from the matching rows - only one row from each event_id, and it needs to be the one with the lowest occ_id value.
i.e.
gen_id | event_id | occ_id | month
------------------------------------
1 | 190 | 1 | 4
2 | 190 | 2 | 4
3 | 190 | 3 | 4
4 | 192 | 1 | 4
5 | 192 | 2 | 4
6 | 192 | 3 | 4
7 | 193 | 1 | 5
8 | 193 | 2 | 5
If I'm looking for events from month = 4, I need to get the events (gen_id): 1,4
and if I'm looking for month = 5 I need to get only event (gen_id): 7
My SQL query right now gets the matching events but with no occ_id filteration:
(it looks something like this right now)
SELECT
event_id,
event_title,
occ_id
FROM
table_name
WHERE month = 4
GROUP BY event_id
ORDER BY
event_id
DESC
I have tried to also use MIN / MAX but I guess it either not the right handler for this case or I'm using it wrong...
You want to filter. One method uses a correlated subquery in the WHERE clause:
select t.*
from table_name t
where t.occ_id = (select min(t2.occ_id)
from table_name t2
where t2.event_id = t.event_id
);
However, the lowest value always seems to be "1", so this might work as well:
select t.*
from table_name t
where t.month = 4 and
t.occ_id = 1;
To add month, you can add it to the outer query:
select t.*
from table_name t
where t.month = 4 and
t.occ_id = (select min(t2.occ_id)
from table_name t2
where t2.event_id = t.event_id and
t2.month = t.month
);
umm,
select t.event_id, t.occ_id, t.month, min(t.gen_id) from (
select event_id,month,min(occ_id) as min_occ_id from t where month=5 group by event_id, month
) t1 join t on t1.min_occ_id = t.occ_id and t1.event_id = t.event_id and t1.month = t.month
group by t.event_id, t.occ_id, t.month;
if columns event_id,occ_id,month make up an UNIQUE KEY, the SQL can be simplified.
select t.event_id, t.occ_id, t.month, t.gen_id from (
select event_id,month,min(occ_id) as min_occ_id from t where month=5 group by event_id, month
) t1 join t on t1.min_occ_id = t.occ_id and t1.event_id = t.event_id and t1.month = t.month

How do I get distinct rows by a column?

I have a huge number of rows that I'd like to get say, last 5 records inserted in that database from 10 different users. If the same user inserted the last 3 rows into database, we must get one row, skip the others two and move to get a row per user, until it count up to 5.
A database like that:
user_id | news_id | title
1 | 1 | foo-1
2 | 2 | foo-2
3 | 3 | foo-3
1 | 4 | baa
4 | 5 | baa0
5 | 6 | baa1
5 | 7 | baa2
6 | 8 | baa3
7 | 9 | baa4
Should return:
user_id | news_id | title
1 | 1 | foo-1
2 | 2 | foo-2
3 | 3 | foo-3
4 | 5 | baa0
5 | 6 | baa1
The current filter was done by PHP, like this:
$used = array();
while ($data = mysql_fetch_array($query)) {
$uid = $data['user_id'];
if(in_array($uid, $used))
continue;
array_push($used, $uid);
// do something with data
}
But I want to refactor it, and do the filter purely by mysql, if possible. I don't know much MySql and that's why I'm having problem to archive this...
Here's what I've tried
select DISTINCT(user_id), news_id, title from XXX
WHERE GROUP BY (news_id) DESC
LIMIT 0,5
How can I do that?
1 way you can do it is to generate a partitioned row number per user and then select 5 records where RowNumber = 1.
SELECT *
FROM
(
SELECT
d.user_id
,d.news_id
,d.title
,(#rn:= if(#uid = user_id, #rn + 1,
if(#uid:=user_id,1,1)
)
) as RowNumber
FROM
Data d
CROSS JOIN (SELECT #uid:=-1, #rn:=0) vars
ORDER BY
user_id
,news_id
) t
WHERE
t.RowNumber = 1
ORDER BY news_id
LIMIT 5;
http://rextester.com/JRIZI7402 - example to show it working
Note you can change the row order by simply changing the ORDER BY statement of the derived table so if you have a column that will signify the latest record e.g. an identity column or a datetime column you can use that, but user_id must be the first criteria to be partitioned correctly.
Do it from your query.
"SELECT * FROM table GROUP BY user_id ORDER BY news_id DESC LIMIT 5"
well, i think this will achieve what you are after.
select user_id, news_id, title from tableName
GROUP BY user_id
ORDER BY news_id DESC
LIMIT 0,5
Hope this helps!

Count occurrences of distinct values in 2 fields

I am trying to find a MySQL query that will find distinct values in a particular field, count the number of occurrences of that value in 2 fields (1_user, 2_user) and then order the results by the count.
example db
+------+-----------+-----------+
| id | 1_user | 2_user |
+------+-----------+-----------+
| 1 | 2 | 1 |
| 2 | 3 | 2 |
| 3 | 8 | 7 |
| 4 | 1 | 8 |
| 5 | 2 | 8 |
| 6 | 3 | 8 |
+------+-----------+-----------+
expected result
user count
----- -----
8 4
2 3
3 2
1 2
The Query
SELECT user, count(*) AS count
FROM
(
SELECT 1_user AS USER FROM test
UNION ALL
SELECT 2_user FROM test
) AS all_users
GROUP BY user
ORDER BY count DESC
Explanation
List all the users in the first column.
SELECT 1_user AS USER FROM test
Combine them with the users from the second column.
UNION ALL
SELECT 2_user FROM test
The trick here is the UNION ALL which preserves duplicate values.
The rest is easy -- select the results you want from the subquery:
SELECT user, count(*) AS count
aggregate by user:
GROUP BY user
and prescribe the order:
ORDER BY count DESC
SELECT u, count(u) AS cnt
FROM (
SELECT 1_user AS u FROM table
UNION ALL
SELECT 2_user AS u FROM table
) subquery
GROUP BY u
ORDER by cnt DESC
Take the 2 queries:
SELECT COUNT(*) FROM table GROUP BY 1_user
SELECT COUNT(*) FROM table GROUP BY 2_user
Now combine them:
SELECT user, SUM(count) FROM
((SELECT 1_user as user FROM table)
UNION ALL
(SELECT 2_user as user FROM table))
GROUP BY user, ORDER BY count DESC;
I think this what you are looking for since your expected result did not include 7
select usr, count(usr) cnt from
(
select user_1 usr from users
union all
select user_2 usr from users
) u
where u.usr in (select user_1 from users)
group by usr
order by count(u.usr) desc

SQL Statement, always list 3 entries of a sort

I have another Problem
I just can show you this on an example:
I got a Table called "myTable" with 7 entries
myTable | id | user_id |
1 1
2 1
3 1
4 1
5 2
6 2
7 2
8 2
9 2
10 2
Now i want to list just 3 entries of any user_id, but i cant find out myself how to.
Please help!
------- EDIT
My result have to look like this:
id=1 | user_id=1
id=2 | user_id=1
id=3 | user_id=1
id=5 | user_id=2
id=6 | user_id=2
id=7 | user_id=2
select * from table as t1
where (select count(*) from table as t2
where t1.user_id = t2.user_id and t2.id < t1.id) <3
SELECT *
FROM table
ORDER BY ...
LIMIT 3
The LIMIT clause takes two arguments: number of rows to return, and an offset if you want to display something other than the first X rows. Details here in the MySQL docs.
If you want only 3 rows, you can use limit :
select * from myTable limit 3;
SELECT * FROM table LIMIT 3
http://dev.mysql.com/doc/refman/5.0/en/select.html

SQL: GROUP BY records and then get last record from each group? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
SQL Server: Only last entry in GROUP BY
I have a table like this:
id| name | attendence
1 | Naveed| 1
2 | Naveed| 1
3 | Adil | 1
4 | Adil | 1
I use following query:
SELECT * FROM `test` WHERE `attendence`=1 GROUP BY name
The result with above query:
id| name | attendence
3 | Adil | 1
1 | Naveed | 1
Question:
Above result group rows by name but show first row from each group. I want to select last row(by id) from each group.
For example:
id| name | attendence
2 | Naveed | 1
4 | Adil | 1
How to write query for above result.
Thanks
SELECT a.*
FROM test a
WHERE a.attendence = 1
AND NOT EXISTS (select 1 from test where name = a.name and id > a.id and attendence = 1)
GROUP BY name
Might not even need the group by anymore.
SELECT MAX("id"), "name" FROM "test" WHERE "attendence" = 1 GROUP BY "name"
SELECT Name, Max(ID) FROM table WHERE attendance = 1 GROUP BY Name
Use the following query:
SELECT * FROM `test` WHERE `attendence`=1 GROUP BY name ORDER BY `id` DESC LIMIT 1
That will only select the row that meets the criteria with the highest id.

Categories