sql sorting inside group by with two column - mysql

My table:
id | request | subject | date
1 | 5 | 1 | 576677
2 | 2 | 3 | 576698
3 | 5 | 1 | 576999
4 | 2 | 3 | 586999
Need to select unique records by two columns(request,subject) with showing last inserted id's.
My query:
SELECT *,MAX(id)
FROM `tbl`
GROUP BY CONCAT(`request_id`, `subject_id`)
HAVING (COUNT(`request_id`)>1 order by MAX(id) desc
But results:
id | request | subject | date
2 | 2 | 3 | 576698
1 | 5 | 1 | 576677
How to get records with id's 3 and 4 ?

Try this:
SELECT MIN(id) id, request, subject, MAX(`date`) `date`
FROM `tbl`
GROUP BY request, subject;
See it run on SQL Fiddle.

You can try this.
SELECT T.*
FROM T
INNER JOIN
(
SELECT MAX(`ID`) as ID,`request`,`subject`
FROM T
GROUP BY `request`,`subject`
HAVING COUNT(`ID`) > 1
)AS T1 ON T.ID = T1.ID
SQLFiddle

Thanks for all. My result is
SELECT MAX(id), id, request, subject, date
FROM `tbl`
GROUP BY request, subject having count(request)>1 order by MAX(id) desc

Related

sql group by with excluded data

My table:
id | request | subject | date
1 | 5 | 1 | 576677
2 | 2 | 3 | 576698
3 | 5 | 1 | 576999
4 | 2 | 3 | 586999
5 | 2 | 7 | 596999
Need to select unique records by two columns(request,subject). But if we have different pairs of request-subject(2-3, 2-7), this records should be excluded from resulted query.
My query now is:
SELECT MAX(id), id, request, subject, date
FROM `tbl`
GROUP BY request, subject
having count(request) > 1
order by MAX(id) desc
How to exclude record with id=4, id=5 from this query? Thanks!
You may group by request, and then check for every group if all subjects in it are equal. You could do it using MIN() and MAX():
SELECT request, MIN(subject) AS subject
FROM table_1
GROUP BY request
HAVING MIN(subject) = MAX(subject)
As for your update, I assume you want all the fields for the max ID in the group (in your example, ID 3). The query would then look like this one:
SELECT *
FROM table_1 t
WHERE t.id IN (SELECT MAX(s.id)
FROM table_1 s
GROUP BY s.request
HAVING MIN(s.subject) = MAX(s.subject))
ORDER BY t.id
You can try this.
select * from MyTable T1
WHERE NOT EXISTS( SELECT * FROM MyTable T2
WHERE T1.id <> T2.id
and T1.request = T2.request
and T1.subject <> T2.subject)
Sql Fiddle

How can I identify if a certain row is the last by using an ID in MySQL

Sorry to confuse you about my title. I am building an auction system and I am having a difficulty in getting the user's winning item.
Example I have a table like this:
the columns are:
id, product_id, user_id, status, is_winner, info, bidding_price, bidding_date
here's my sql fiddle:
http://sqlfiddle.com/#!9/7097d/1
I want to get every user's item that they already win. So I need to identify if they are the last who bid in that item.
I need to filter it using a user_id.
If I do a query like this:
SELECT MAX(product_id) AS product_id FROM auction_product_bidding
WHERE user_id = 3;
it will get only the product_id that is 12 and the product_id of 9 did not get. Product ID 9 is also that last bid of the user_id 3.
Can you help me? I hope you got my point. Thanks. Sorry if my question a little bit confusing.
According to your question, seems 11 is also what you want, try this query:
SELECT apd.product_id
FROM auction_product_bidding apd
JOIN (
SELECT MAX(bidding_date) AS bidding_date, product_id
FROM auction_product_bidding
GROUP BY product_id
) t
ON apd.product_id = t.product_id
AND apd.bidding_date = t.bidding_date
WHERE apd.user_id = 3;
Check Demo Here
select id,product_id,user_id,status,is_winner,info,bidding_price,bidding_date,rank
from
( SELECT apb.*,
greatest(#rank:=if(product_id=#prodGrp,#rank+1,1),-1) as rank,
#prodGrp:=product_id as dummy
FROM auction_product_bidding apb
cross join (select #prodGrp:=-1,#rank:=0) xParams
order by product_id,bidding_date DESC
) xDerived
where user_id=3 and rank=1;
That user won 9,11,12
+----+------------+---------+--------+-----------+------+---------------+---------------------+------+
| id | product_id | user_id | status | is_winner | info | bidding_price | bidding_date | rank |
+----+------------+---------+--------+-----------+------+---------------+---------------------+------+
| 60 | 9 | 3 | | 0 | | 75000.00 | 2016-08-02 16:31:23 | 1 |
| 59 | 11 | 3 | | 0 | | 15000.00 | 2016-08-02 12:04:16 | 1 |
| 68 | 12 | 3 | | 0 | | 18000.00 | 2016-08-10 09:20:01 | 1 |
+----+------------+---------+--------+-----------+------+---------------+---------------------+------+
SELECT product_id FROM auction_product_bidding where bidding_price= any
(select max(bidding_price) from auction_product_bidding group by product_id)
and user_id='3';
select * from
(select product_id,user_id,max(bidding_price) from
(select * from auction_product_bidding order by bidding_price desc) a
group by product_id) b
where user_id=3;
Answer:
product_id user_id max(bidding_price)
9 3 75000
11 3 15000
12 3 18000
An idea could be to sort the table desc by date and select every distinct row by product_id and customer_id. Something like
SELECT DISTINCT prod_id, user_id FROM (
SELECT * FROM auction_product_bidding ORDER BY date DESC
)
You want everything that bids last in 3, is it right ?

Get second highest values from a table

I have a table like this:
+----+---------+------------+
| id | conn_id | read_date |
+----+---------+------------+
| 1 | 1 | 2010-02-21 |
| 2 | 1 | 2011-02-21 |
| 3 | 2 | 2011-02-21 |
| 4 | 2 | 2013-02-21 |
| 5 | 2 | 2014-02-21 |
+----+---------+------------+
I want the second highest read_date for particular 'conn_id's i.e. I want a group by on conn_id. Please help me figure this out.
Here's a solution for a particular conn_id :
select max (read_date) from my_table
where conn_id=1
and read_date<(
select max (read_date) from my_table
where conn_id=1
)
If you want to get it for all conn_id using group by, do this:
select t.conn_id, (select max(i.read_date) from my_table i
where i.conn_id=t.conn_id and i.read_date<max(t.read_date))
from my_table t group by conn_id;
Following answer should work in MSSQL :
select id,conn_id,read_date from (
select *,ROW_NUMBER() over(Partition by conn_id order by read_date desc) as RN
from my_table
)
where RN =2
There is an intresting article on use of rank functions in MySQL here : ROW_NUMBER() in MySQL
If your table design as ID - date matching (ie a big id always a big date), you can group by id, otherwise do the following:
$sql_max = '(select conn_id, max(read_date) max_date from tab group by 1) as tab_max';
$sql_max2 = "(select tab.conn_id,max(tab.read_date) max_date2 from tab, $sql_max
where tab.conn_id = tab_max.conn_id and tab.read_date < tab_max.max_date
group by 1) as tab_max2";
$sql = "select tab.* from tab, $sql_max2
where tab.conn_id = tab_max2.conn_id and tab.read_date = tab_max2.max_date2";

How to make a query to GROUP BY x DESC

The following SELECT statement
select *
from messages
where receiverID = '5'
group BY senderID
order by id DESC
database:
id | senderID | receiverID | message
1 | 245 | 5 | test 1
2 | 89 | 5 | test 2
3 | 79 | 5 | test 3
4 | 245 | 5 | test 4
5 | 245 | 5 | test 5
For senderID=245 I expected to return the row with id=5 , but it dosent it returns row with id=1, but i want the last row. How to achieve that ?
returns:
id | senderID | receiverID | message
1 | 245 | 5 | test 1
2 | 89 | 5 | test 2
3 | 79 | 5 | test 3
Ohh I made it :D
so this is the code that worked,for anyone with similar question
SELECT * FROM ( SELECT * FROM messages WHERE
receiverID = '5' ORDER BY id DESC) AS m GROUP BY senderID ORDER BY id DESC
This is not possible. You have to do something like:
[...] WHERE `id` = (SELECT MAX(`id`) FROM `messages` WHERE `receiverID` = '5')
Personally I'd consider a subquery, something along the lines of this should do the job for you
SELECT messagesOrdered.*
FROM (
SELECT *
FROM messages
WHERE receiverID = '5'
ORDER BY id DESC
) AS messagesOrdered
GROUP BY senderID
You may wish to check what keys you have set up depending on how large the table is.
The problem with using MAX is that if you use MAX on the id field then it will get the number you are looking for, however using MAX on another field does not get the data that matches that id. Using the subquery method, the inner query is doing the sorting and then the GROUP on the outside will group based on the order of rows in the inner query.
SELECT * FROM messages m
JOIN
( SELECT senderID, MAX(id) AS last
FROM messages
WHERE receiverID = '5'
GROUP BY senderID ) mg
ON m.id = mg.last
Not sure I understand your question completely, but it sounds to me like you want:
select max(id),
senderId,
max(receiverId),
max(message)
from messages
where receiverID = '5'
group BY senderID
order by id DESC
Note that you need to include message into your aggregate as well, otherwise you'll get unpredicatable results (other DBMS wouldn't allow leaving out the max(message) but MySQL will simply return a random row from the group).
Here it goes mine :)
select m1.* from messages m1
left join messages m2
on m1.senderid = m2.senderid and m1.id < m2.id
where m2.id is null and receiverID = '5'
Given your example this would return:
+----+----------+------------+---------+
| ID | SENDERID | RECEIVERID | MESSAGE |
+----+----------+------------+---------+
| 2 | 89 | 5 | test 2 |
| 3 | 79 | 5 | test 3 |
| 5 | 245 | 5 | test 5 |
+----+----------+------------+---------+

Sort data before using GROUP BY?

I have read that grouping happens before ordering, is there any way that I can order first before grouping without having to wrap my whole query around another query just to do this?
Let's say I have this data:
id | user_id | date_recorded
1 | 1 | 2011-11-07
2 | 1 | 2011-11-05
3 | 1 | 2011-11-06
4 | 2 | 2011-11-03
5 | 2 | 2011-11-06
Normally, I'd have to do this query in order to get what I want:
SELECT
*
FROM (
SELECT * FROM table ORDER BY date_recorded DESC
) t1
GROUP BY t1.user_id
But I'm wondering if there's a better solution.
Your question is somewhat unclear but I have a suspicion what you really want is not any GROUP aggregates at all, but rather ordering by date first, then user ID:
SELECT
id,
user_id,
date_recorded
FROM tbl
ORDER BY date_recorded DESC, user_id ASC
Here would be the result. Note reordering by date_recorded from your original example
id | user_id | date_recorded
1 | 1 | 2011-11-07
3 | 1 | 2011-11-06
2 | 1 | 2011-11-05
5 | 2 | 2011-11-06
4 | 2 | 2011-11-03
Update
To retrieve the full latest record per user_id, a JOIN is needed. The subquery (mx) locates the latest date_recorded per user_id, and that result is joined to the full table to retrieve the remaining columns.
SELECT
mx.user_id,
mx.maxdate,
t.id
FROM (
SELECT
user_id,
MAX(date_recorded) AS maxdate
FROM tbl
GROUP BY user_id
) mx JOIN tbl t ON mx.user_id = t.user_id AND mx.date_recorded = t.date_recorded
Iam just using the technique
"Using order clause before group by inserting it in group_concat clause"
SELECT SUBSTRING_INDEX(group_concat(cast(id as char)
ORDER BY date_recorded desc),',',1),
user_id,
SUBSTRING_INDEX(group_concat(cast(`date_recorded` as char)
ORDER BY `date_recorded` desc),',',1)
FROM data
GROUP BY user_id