selecting every newest row for specific values - mysql

Hi I have a table like so:
SN | User | is_borrowed | date
105 | 1 | 1 |2019-1-1
105 | 1 | 0 |2019-2-1
105 | 1 | 1 |2019-3-1
106 | 2 | 1 |2019-4-1
107 | 1 | 1 |2019-5-1
106 | 2 | 0 |2019-6-1
106 | 2 | 1 |2019-8-1
107 | 1 | 0 |2019-9-1
107 | 2 | 1 |2019-10-1
Wanted output is to show what is borrowed (not returned) and user=1:
SN | User | is_borrowed | date
105 | 1 | 1 |2019-3-1
Output for User=2 and borrowed (not returned):
SN | User | is_borrowed | date
106 | 2 | 1 |2019-8-1
107 | 2 | 1 |2019-10-1
In summary I want a list of devices currently borrowed that are not returned for each user. Sadly nothing comes to my mind tho :/

looking to your expected result seems you are looking for the max(date) for SN, user where is_borrowed = 1
select SN, user, is_borrowed, max(date)
from my_table
where is_borrowed = 1
group by SN, user, is_borrowed
or for the device actual borrowed
Select * from my_table m
inner join t (
select SN, is_borrowed, max(date) max_date
from my_table
where is_borrowed = 1
group by SN, is_borrowed
) t on t.SN = m.SN AND t.max_date = m.date

SELECT t.sn, t.user, t.is_borrowed, t.date
FROM TABLE_NAME t
WHERE t.is_borrowed = 1
AND t.date =
(
SELECT MAX(x.date)
FROM TABLE_NAME x
WHERE x.user = t.user
)
AND (
SELECT xx.is_borrowed
FROM TABLE_NAME xx
WHERE t.sn = xx.sn
AND t.date < xx.date
) <> 0
;

Related

selecting only newest row with specific value

Table:
person | borrow_date | is_borrowed | SN | date | id
1 | 2019-01-10...| 1 | 20 |2019-01-10...| 6
3 | 2019-01-09...| 3 | 10 |2019-01-09...| 5
1 | 2019-01-08...| 1 | 10 |2019-01-08...| 4
2 | 2019-01-08...| 1 | 10 |2019-01-08...| 3
1 | NULL | 2 | 20 |2019-01-07...| 2
1 | NULL | 2 | 10 |2019-01-07...| 1
My wanted output is to select newest rows where "is_borrowed" equals 1 and grouped by SN, so that when the query is executed with person=2 or person=3 then it would retrieve empty set. Whereas for person=1 it would give back two rows.
Wanted output (where person=1):
person | borrow_date | is_borrowed | SN | date |id
1 | 2019-01-10...| 1 | 20 | 2019-01-10...|6
1 | 2019-01-08...| 1 | 10 | 2019-01-08...|4
Wanted output (where person=2):
EMPTY SET
Wanted output (where person=3):
EMPTY SET
This is my current query and it sadly doesn't work.
SELECT a.SN, a.is_borrowed,a.max(date) as date, a.person
FROM table a
INNER JOIN (SELECT SN, MAX(date) as date, osoba from table where person like
"2" group by SN) as b
ON a.SN=b.SN and a.date=b.date
WHERE a.person like "2" and a.is_borrowed=1
If I correctly understood you from the question and the comment you made under it, here's one way to do it without specifying the person:
select *
from TableName as p
inner join (select max(borrow_date) as borrow_date,
SN
FROM TableName
where is_borrowed = 1
group by SN) as p2
on p.borrow_date = p2.borrow_date and p.SN = p2.SN
This should give you the result you're looking for. Here's a demo.
Note that I had to change the borrowed_date values in the table since yours contain hours and minutes while I didn't add those.
You can always specify it for each person by adding a where clause after the join.
select p.person,
p.borrow_date,
p.is_borrowed,
p.SN,
p.date,
p.id
from TableName as p
inner join (select max(borrow_date) as borrow_date,
SN
FROM TableName
where is_borrowed = 1
group by SN) as p2
on p.borrow_date = p2.borrow_date and p.SN = p2.SN
where p.person = '1'
Output:
person | borrow_date | is_borrowed | SN | date | id
1 | 2019-01-10 | 1 | 20 | 2019-01-10 | 6
1 | 2019-01-08 | 1 | 10 | 2019-01-08 | 4
While where p.person = '2' and where p.person = '3' will return empty sets.

Mysql: Get the rows with max value grouped by a field

Suppose I have a table messages like this:
id sender receiver content created_at
1 100 101 Hi 2015-12-01
2 100 101 Hello 2015-12-02
3 100 101 World 2015-11-02
4 103 101 Like 2015-11-05
5 103 101 Do 2015-11-04
6 105 102 ..................
With the receiver specified, I want to get the latest message and number of messages from each user, i.e. for user 101, I want to get:
2 100 101 Hello 2015-12-02 3
4 103 101 Like 2015-11-05 2
Is it possible to do that with a single statement or what's the most elegant way ?
Aggregate the information for 101 in a subquery, and then join that back to the original table:
select m.*, mm.maxca
from messages m join
(select m2.receiver, max(m2.created_at) as maxca, count(*) as cnt
from messages m2
where m2.receiver = 101
) mm
on m.receiver = mm.receiver and m.created_at = mm.created_at
where m.receiver = 101 ;
Idea here is to get latest record which can be acheived by ordering by created_at and then using group by to get the count.
SELECT a.id,a.sender,a.receiver,a.content,a.created_at,count(a.sender) from (Select * from messages order by created_at desc) a group by sender ;
SELECT x.*
, y.total
FROM my_table x
JOIN
( SELECT receiver
, sender
, MAX(created_at) max_created_at
, COUNT(*) total
FROM my_table
GROUP
BY receiver
, sender
) y
ON y.receiver = x.receiver
AND y.sender = x.sender
AND y.max_created_at = x.created_at
-- [WHERE receiver = 101]
;
+----+--------+----------+---------+------------+-------+
| id | sender | receiver | content | created_at | total |
+----+--------+----------+---------+------------+-------+
| 2 | 100 | 101 | Hello | 2015-12-02 | 3 |
| 4 | 103 | 101 | Like | 2015-11-05 | 2 |
| 6 | 105 | 102 | Re | 2015-11-04 | 1 |
+----+--------+----------+---------+------------+-------+
http://www.sqlfiddle.com/#!9/3fef7/1

Query to find result with max rundate with max horizon

Table data looks like:
EventID | MPID | rundate | Horizon | otherData
1 | 1 | 23-Jun-2014 | 360 | other value
1 | 1 | 23-Jun-2014 | 365 | pther value
1 | 1 | 23-Jun-2014 | 300 | pther value
1 | 1 | 22-Jun-2014 | 700 | pther value
1 | 2 | 23-Jun-2014 | 400 | other value
1 | 2 | 23-Jun-2014 | 340 | oth
2 | 3 | 23-Jun-2014 | 360 | pther value
2 | 3 | 23-Jun-2014 | 300 | pther value
2 | 3 | 22-Jun-2014 | 365 | pther value
I want to select the max rundate for each event and marketplace group and then select max horizon among that group and then print the entire row.
Desired Result is :
EventID | MPID | rundate | Horizon | otherData
1 | 1 | 23-Jun-2014 | 365 | pther value
1 | 2 | 23-Jun-2014 | 400 | other value
2 | 3 | 23-Jun-2014 | 360 | pther value
Please let me know the SQL query for this.
I tried following query but its not working:
SELECT * from dsie_result_overalls where id in (
SELECT k.id from dsie_result_overalls k,
(
SELECT a.event_id, a.marketplaceid, MAX(a.horizon) as horizon FROM dsie_result_overalls a,
(
SELECT id, event_id, marketplaceid, MAX(rundate) AS rundate FROM dsie_result_overalls
GROUP BY event_id, marketplaceid
) b
WHERE a.event_id = b.event_id AND a.marketplaceid = b.marketplaceid AND a.rundate = b.rundate
GROUP BY a.event_id, a.marketplaceid
) l WHERE k.event_id = l.event_id AND k.marketplaceid = l.marketplaceid AND k.horizon = l.horizon
);
It selects the multiple rundate for max horizon.
Try this query
Select T.* From Tbl T JOIN
( Select Max(S.Horizon) MaxHorizon,Max(S.rundate) As dte,S.EventID,S.MPID
From Tbl S Join
( Select T1.EventID,Max(T1.rundate) As Maxrundate,T1.MPID
From Tbl T1 Group By T1.EventID,T1.MPID
) JR On S.rundate = JR.Maxrundate AND S.EventID = JR.EventID AND S.MPID = JR.MPID
Group By S.MPID,S.EventID
)R ON T.Horizon = R.MaxHorizon AND T.EventID = R.EventID AND T.MPID = R.MPID AND T.rundate = R.dte
Fiddle Demo
Output would be
EventID | MPID | rundate | Horizon | otherData
1 | 1 | 23-Jun-2014 | 365 | pther value
1 | 2 | 23-Jun-2014 | 400 | other value
2 | 3 | 23-Jun-2014 | 360 | pther value
The proper way...
SELECT x.*
FROM dsie_result_overalls x
JOIN
( SELECT a.eventid
, a.mpid
, a.rundate
, MAX(a.horizon) max_horizon
FROM dsie_result_overalls a
JOIN
( SELECT eventid
, mpid
, MAX(rundate) max_rundate
FROM dsie_result_overalls
GROUP
BY eventid
, mpid
) b
ON b.eventid = a.eventid
AND b.mpid = a.mpid
AND b.max_rundate = a.rundate
GROUP
BY a.eventid
, a.mpid
, a.rundate
) y
ON y.eventid = x.eventid
AND y.mpid = x.mpid
AND y.rundate = x.rundate
AND y.max_horizon = x.horizon;
The hack way...
SELECT *
FROM
( SELECT *
FROM dsie_result_overalls
ORDER
BY eventid
, mpid
, rundate DESC
, horizon DESC
) x
GROUP
BY eventid
, mpid;
The old-fashioned way...
SELECT x.*
FROM dsie_result_overalls x
LEFT
JOIN dsie_result_overalls y
ON y.eventid = x.eventid
AND y.mpid = x.mpid
AND (y.rundate > x.rundate OR (y.rundate = x.rundate AND y.horizon > x.horizon))
WHERE y.id IS NULL;
You can group by event and marketplace an get the MAX(rundate). The MAX(horizon) you can get follow.
SELECT eventid
, mpid
, MAX(rundate) rundate
, SUBSTRING_INDEX(GROUP_CONCAT(horizon ORDER BY rundate DESC, horizon DESC),',',1) horizon
FROM dsie_result_overalls
GROUP
BY eventid
, mpid

Select monthly counts of data across two tables in mysql

I have two tables, lastfm_scrobbles and lastfm_annotations. Example data:
mysql> select * from lastfm_scrobbles limit 5;
+---------+---------+-----------+---------------------+
| user_id | item_id | artist_id | scrobble_time |
+---------+---------+-----------+---------------------+
| 1469 | 45651 | 1 | 2010-06-30 13:57:42 |
| 1469 | 45651 | 1 | 2011-03-28 15:43:37 |
| 6872 | 45653 | 1 | 2013-08-03 15:07:44 |
| 7044 | 1370 | 1 | 2007-03-26 17:07:26 |
| 7044 | 1370 | 1 | 2007-08-24 18:41:35 |
+---------+---------+-----------+---------------------+
mysql> select * from lastfm_annotations limit 5;
+---------+---------+-----------+--------+------------+
| user_id | item_id | artist_id | tag_id | tag_month |
+---------+---------+-----------+--------+------------+
| 121 | 1330412 | 1330412 | 475 | 2006-12-01 |
| 121 | 1330412 | 1330412 | 517 | 2006-12-01 |
| 121 | 1330412 | 1330412 | 7280 | 2006-12-01 |
| 121 | 1330412 | 1330412 | 21384 | 2006-12-01 |
| 121 | 1330412 | 1330412 | 27872 | 2006-12-01 |
+---------+---------+-----------+--------+------------+
Furthermore, I have a user information table (lastfm_users). The details of this aren't important, but what is relevant is that the query:
select user_id from lastfm_users where scrobbles_recorded==1;
Returns the users I care about for the purposes of this question.
Ok, with that preamble out of the way: I need a query that will get me, for those users, the total number of entries they have in both the scrobbles and annotations tables for each month. In other words, the result should look something like:
user_id y m scrobble_count anno_count
123 2006 3 100 50
456 2008 11 321 10
... and so on
Make sense? I believe the query I want is a combination of the following:
select year(tag_month) as y, month(tag_month) as m, count(*) as anno_count
from lastfm_annotations where user_id in (select user_id from
lastfm_users where scrobbles_recorded=1)
group by user_id, year(tag_month), month(tag_month);
select year(scrobble_time) as y, month(scrobble_time) as m, count(*) as scrobble_count
from lastfm_scrobbles where user_id in (select user_id from
lastfm_users where scrobbles_recorded=1)
group by user_id, year(scrobble_time), month(scrobble_time);
But I'm not certain of the correct way to generate the join query to get the result I want. Suggestions?
You can try
select user_id, y, m,
coalesce(sum(case when source = 1 then total end), 0) anno_count,
coalesce(sum(case when source = 2 then total end), 0) scrobble_count
from
(
select 1 source, a.user_id, year(tag_month) y, month(tag_month) m, count(*) total
from lastfm_annotations a join lastfm_users u
on a.user_id = u.user_id
where u.scrobbles_recorded = 1
group by user_id, year(tag_month), month(tag_month)
union all
select 2 source, s.user_id, year(scrobble_time), month(scrobble_time), count(*)
from lastfm_scrobbles s join lastfm_users u
on s.user_id = u.user_id
where u.scrobbles_recorded = 1
group by user_id, year(scrobble_time), month(scrobble_time)
) q
group by user_id, y, m
or just
select user_id, y, m,
sum(case when source = 1 then 1 else 0 end) anno_count,
sum(case when source = 2 then 1 else 0 end) scrobble_count
from
(
select 1 source, a.user_id, year(tag_month) y, month(tag_month) m
from lastfm_annotations a join lastfm_users u
on a.user_id = u.user_id
where u.scrobbles_recorded = 1
union all
select 2 source, s.user_id, year(scrobble_time), month(scrobble_time)
from lastfm_scrobbles s join lastfm_users u
on s.user_id = u.user_id
where u.scrobbles_recorded = 1
) q
group by user_id, y, m;
Here is SQLFiddle demo

Joining tables and making count operation - MySQL

I have those tables:
Members
---------------------------
MemberID | Name |.....
1
2
3
4
---------------------------
RentedMovies
---------------------------
MemberID | MovieID | DateOfLease | ReturnDate | .....
1 | 1 | 2012-12-20 | 2013-01-05
1 | 2 | 2012-12-15 | 2012-12-30
1 | 3 | 2012-12-16 | 2013-01-06
2 | 1 | 2012-12-17 | 2012-12-18
2 | 4 | 2012-12-18 | 2013-01-05
3 | 1 | 2012-12-19 | 2013-01-04
I need to get this:
--------------------------------------------------------
MemberID | NumberOfRentedMovies | ReturnData < curdate())
1 | 3 | 1
2 | 2 | 1
3 | 1 | 0
4 | 0 | 0
---------------------------------------------------------
And i used next code:
SELECT Members.MemberID,
COUNT(rented.MemberID) AS NumberOfRentedMovies,
COUNT(notTakenBackOnTime.idClana) AS NumberOfMoviesLate
FROM Members
left JOIN RentedMovies as rented ON rented.MemberID = Members.MemberID
left JOIN RentedMovies as notTakenBackOnTime ON notTakenBackOnTime.MemberID
= Members.MemberID AND notTakenBackOnTime.ReturnDate< CURDATE()
group by Members.MemberID
But it doesnt work corrextly!
And I also tried with this:
SELECT MemberID,my,my2
FROM Members as mem
JOIN (SELECT COUNT(* )AS my FROM RentedMovies) b
ON b.MemberID = mem.MemberID
JOIN (SELECT COUNT(* )AS my2 FROM RentedMovies WHERE ReturnDate< CURDATE()) c
ON c.MemberID = mem.MemberID
But i got some errors!
So the question is how to accomplish right solution?
You were close. Try this:
SELECT M.MemberID,
COUNT(RM.MemberID) NumberOfRentedMovies,
SUM(CASE WHEN RM.ReturnDate < CURDATE() THEN 1 ELSE 0 END) ReturnData
FROM Members M
LEFT JOIN RentedMovies RM
ON M.MemberID = RM.MemberID
GROUP BY M.MemberID
The desired result you showed can be accomplished by:
SELECT MemberID,
COALESCE(COUNT(MovieID), 0) AS NumberOfRentedMovies,
COALESCE(SUM(ReturnDate < CURDATE()), 0) AS NotYetReturned
FROM Members
LEFT JOIN RentedMovies USING (MemberID)
GROUP BY MemberID
See it in action: http://sqlfiddle.com/#!2/a192c/1