Select last record of each person - mysql

I have the following tables
tbl_investors
id | first_name | last_name |
---------------------------------------
1 | Jon | Cold |
2 | Rob | Ark |
3 | Rickon | Bolt |
tbl_investors_ledger
id | investor_id | amount |
------------------------------------
1 | 1 | 500 |
2 | 2 | 200 |
3 | 2 | 250 |
4 | 2 | 300 |
5 | 3 | 10 |
6 | 1 | 550 |
7 | 3 | 20 |
I just want to return all investors with their latest amount. Ex, Jon Cold with 550, Rob Ark 300 and Rickon Bolt 20, alphabetically with their last name.
I have an existing query but it will not return the latest amount of the investor. Can someone help me what i'm doing wrong?
SELECT t1.*, t2.*
FROM ".tbl_investors." t1
LEFT JOIN ".tbl_investors_ledger." t2
ON t1.id = t2.investor_id
LEFT JOIN (SELECT t.investor_id, max(t.id) as tid
FROM ".tbl_investors_ledger." t ) tt
ON tt.investor_id = t2.investor_id AND tt.tid = t2.id
GROUP BY t2.investor_id
ORDER BY t1.last_name

You can use GROUP_CONCAT and SUBSTRING_INDEX together
SELECT I.*
, SUBSTRING_INDEX(GROUP_CONCAT(L.amount ORDER BY L.id DESC), ',', 1) AS LastAmount
FROM tbl_investors AS I
LEFT JOIN tbl_investors_ledgers AS L
ON L.investor_id = I.id
GROUP BY I.id
ORDER BY I.last_name
Here a demo from SQLFiddle, many thanks to #zakhefron :)

Try this;)
SELECT t1.*, t2.*
FROM tbl_investors t1
LEFT JOIN tbl_investors_ledger t2
ON t1.id = t2.investor_id
INNER JOIN (
SELECT t.investor_id, max(t.id) as tid
FROM tbl_investors_ledger t GROUP BY t.investor_id) tt
ON tt.investor_id = t2.investor_id AND tt.tid = t2.id
ORDER BY t1.last_name
SQLFiddle DEMO
And check related OP Retrieving the last record in each group and this blog How to select the first/least/max row per group in SQL, you can find more solutions for your question.

Related

GROUB BY in MySQL JOIN query

There is two table. First one which stores fee per user
+----+----+----+
| id |uid |fee |
+----+----+----+
| 1 |P001|100 |
+----+----+----+
| 2 |P002|200 |
+----+----+----+
| 3 |P003|250 |
+----+----+----+
| 4 |P004|100 |
+----+----+----+
| 5 |P001|200 |
+----+----+----+
| 6 |P002|200 |
+----+----+----+
| 7 |P003|250 |
+----+----+----+
| 8 |P004|100 |
+----+----+----+
second one stores user classification
+----+-----+
|uid |class|
+----+-----+
|P001| 1 |
+----+-----+
|P002| 1 |
+----+-----+
|P003| 2 |
+----+-----+
|P004| 3 |
+----+-----+
I want to show their sum grouped by class as following
1 - 700
2 - 500
3 - 200
How should I write this SQL query? Thanks in advance.
Suppose first table tab1 and second1 is tab2
select t2.class,sum(t1.fee) from tab2 t2 inner join tab1 t1 on t2.uid=t1.uid
group by t2.class
Try this
SELECT a.class, SUM(b.fee)
FROM user_classification a
INNER JOIN user_fees b
ON a.uid = b.uid
GROUP BY a.class
ORDER BY a.class ASC
Try this:
SELECT class, SUM(fee)
FROM table1 t1
LEFT JOIN table2 t2
ON t1.uid = t2.uid
GROUP BY class
SELECT COUNT(*) AS Expr28, SInv_D.fTransUnitPrice AS fTransUnitPrice, SInv_D.fExtended AS Expr2, SInv_D.fTransQty * SInv_D.fTransUnitPrice AS fTransUnitPrice,
SInv.cMode AS cMode, SInv.cInvoicNum AS cInvoicNum, SInv.dOperaDate AS dOperaDate, SInv_D.cMode AS Expr9, SInv_D.cInvoicNum AS Expr10,
SInv_D.cItCode AS cItCode, SInv_D.cItName AS cItName, SInv_D.cTransUnit AS cTransUnit, SUM(SInv_D.fTransQty) AS fTransQty, SInv.cMode AS Expr4,
SInv.cInvoicNum AS Expr16, SInv_D.cItCode AS Expr15, SInv_D.fTransUnitPrice AS Expr19, SInv.dIssueDate AS Expr20, WareDef.cCode AS Expr21,
WareDef.cName1 AS Expr22, item.cUnitR AS Expr24, item.cName1 AS Expr25, item.fCostSTDR AS Expr26, SInv.cWare1 AS Expr27, item.cCode AS cCode, I.Expr999,
I.cItCode AS Expr1
FROM SInv LEFT OUTER JOIN
WareDef ON SInv.cWare1 = WareDef.cCode LEFT OUTER JOIN
SInv_D ON SInv.cInvoicNum = SInv_D.cInvoicNum AND SInv.dIssueDate = SInv_D.dIssueDate LEFT OUTER JOIN
item ON SInv_D.cItCode = item.cCode INNER JOIN
(SELECT SUM(fTransQty) AS Expr999, cItCode
FROM dbo.sinv_D
GROUP BY sinv_D.cItCode) I ON I.cItCode = SInv_D.cItCode
WHERE (SInv.dIssueDate BETWEEN 20130102 AND 20130109) AND (SInv.cWare1 = '003') AND (SInv.cMode = '122') AND (SInv_D.cMode = '122')
GROUP BY SInv_D.cItCode, SInv_D.fTransUnitPrice, SInv_D.fExtended, SInv_D.fTransQty, SInv.cMode, SInv.cInvoicNum, SInv.dOperaDate, SInv_D.cMode, SInv_D.cInvoicNum,
SInv_D.cItName, SInv_D.cTransUnit, SInv.dIssueDate, WareDef.cCode, WareDef.cName1, item.cUnitR, item.cName1, item.fCostSTDR, SInv.cWare1, item.cCode,
I.Expr999, I.cItCode

MySQL - Count only if the last associated_statut = 2

Alright, I have those columns on MySQL :
id
id_conv
associated_statut
The associated_statut is a number between 1 and 7.
What I want to do is to count only the id_conv if the LAST associated_statut for this id_conv is 2 for example.
Example :
-----------------------------------------------
| id | id_conv | associated_statut |
-----------------------------------------------
| 1 | 15 | 1 |
| 2 | 15 | 2 |
| 3 | 15 | 2 |
| 4 | 15 | 4 |
| 5 | 15 | 2 |
| 6 | 15 | 3 |
The id_conv would NOT be counted if I want the associated_statut = 2, because the last associated_statut for this id_conv is 3.
I already tried this query :
SELECT COUNT(DISTINCT id_conv) FROM MyTable WHERE associated_statut = 2
But this doesn't returns what I want.
Is there a way to do this in SQL ?
Thanks.
Maybe, this will work for you:
SELECT count(t1.id) FROM mytable t1
INNER JOIN (SELECT id_conv, MAX(id) id FROM foo GROUP BY id_conv) t2
ON t1.id = t2.id
WHERE t1.associated_statut = 2
SELECT COUNT(sub1.id_conv) FROM MyTable
INNER JOIN
(
SELECT DISTINCT id, FIRST(associated_statut ORDER BY id DESC)
group by id_conv
recent FROM MyTable
) sub1 ON sub1.id = MyTable.id
WHERE sub1.recent_associated_statut = 2
We can do same thing without sub query. It will take less time when you have more data.
SELECT count(t1.id) FROM
mytable t1
LEFT JOIN
mytable t2
ON t1.id_conv = t2.id_conv
AND t1.id < t2.id
WHERE t2.id IS NULL
AND t1.associated_statut = 2;

Get min price id without inner select

I have a table called a with this data:
+-----+-----------+-------+
| id | parent_id | price |
+-----+-----------+-------+
| 1 | 1 | 100 |
| 2 | 1 | 200 |
| 3 | 1 | 99 |
| 4 | 2 | 1000 |
| 5 | 2 | 999 |
+-----+-----------+-------+
I want to get the id of min pirce for each parent_id.
There is any way to get this result without subquery?
+-----+-----------+-------+
| id | parent_id | price |
+-----+-----------+-------+
| 3 | 1 | 99 |
| 5 | 2 | 999 |
+-----+-----------+-------+
SELECT D1.id, D1.parent_id, D1.price
FROM Data D1
LEFT JOIN Data D2 on D2.price < D1.price AND D1.parent_id = D2.parent_id
WHERE D2.id IS NULL
Here is a shot at how to do it without subqueries. I haven't tested, let me know if it works!
SELECT t.id, t.parent_id, t.price
FROM table t
LEFT JOIN table t2
ON (t.parent_id = t2.parent_id AND t.price > t2.price)
GROUP BY t.id, t.parent_id, t.price
HAVING COUNT(*) = 1 AND max(t2.price) is null
ORDER BY t.parent_id, t.price desc;
Try this:
SELECT T1.id,T2.parent_id,T2.price FROM
(SELECT id,price
FROM TableName) T1
INNER JOIN
(
SELECT parent_id,MIN(price) as price
FROM TableName
GROUP BY parent_id) T2 ON T1.price=T2.price
See result in SQL Fiddle.
Try group by,
SELECT parent_id,min(price)
FROM TableName
GROUP BY parent_id
You can do this with a LEFT JOIN
SELECT a.id, a.parent_id, a.price
FROM a
LEFT JOIN a AS b ON b.price < a.price AND b.parent_id = a.parent_id
WHERE b.id IS NULL
Find the results at this fiddle:
http://sqlfiddle.com/#!2/09c888/10
You can try this without using any join or subquery you will surely get the desired result.
SELECT TOP 2 FROM a ORDER BY price

Mysql - Select at least one or select none

I have a table as so...
----------------------------------------
| id | name | group | number |
----------------------------------------
| 1 | joey | 1 | 2 |
| 2 | keidy | 1 | 3 |
| 3 | james | 2 | 2 |
| 4 | steven | 2 | 5 |
| 5 | jason | 3 | 2 |
| 6 | shane | 3 | 3 |
----------------------------------------
I'm running a select like so:
SELECT * FROM table WHERE number IN (2,3);
The problem im trying to solve is that I want to only grab get results from groups that have 1 or more rows of each number. For instance the above query is returning id's 1-2-3-5-6, when I'd like the results to exclude id 3 since the group of '2' can only return 1 result for the number of '2' and not for BOTH 2 and 3, since there's no row with the number 3 for the group 2 i'd like it to not even select id 3 at all.
Any help would be great.
Try it this way
SELECT *
FROM table1 t
WHERE number IN(2, 3)
AND EXISTS
(
SELECT *
FROM table1
WHERE number IN(2, 3)
AND `group` = t.`group`
GROUP BY `group`
HAVING MAX(number = 2) > 0
AND MAX(number = 3) > 0
)
or
SELECT *
FROM table1 t JOIN
(
SELECT `group`
FROM table1
WHERE number IN(2, 3)
GROUP BY `group`
HAVING MAX(number = 2) > 0
AND MAX(number = 3) > 0
) q
ON t.`group` = q.`group`;
or
SELECT *
FROM table1
WHERE `group` IN
(
SELECT `group`
FROM table1
WHERE number IN(2, 3)
GROUP BY `group`
HAVING MAX(number = 2) > 0
AND MAX(number = 3) > 0
);
Sample output (for both queries):
| ID | NAME | GROUP | NUMBER |
|----|-------|-------|--------|
| 1 | joey | 1 | 2 |
| 2 | keidy | 1 | 3 |
| 5 | jason | 3 | 2 |
| 6 | shane | 3 | 3 |
Here is SQLFiddle demo
On this, you can approach from a fun way with multiple joins for what you WANT qualified, OR, apply a prequery to get all qualified groups as others have suggested, but readability is a bit off for me..
Anyhow, here's an approach going through the table once, but with joins
select DISTINCT
T.id,
T.Name,
T.Group,
T.Number
from
YourTable T
Join YourTable T2
on T.Group = T2.Group AND T2.Group = 2
Join YourTable T3
on T.Group = T3.Group AND T3.Group = 3
where
T.Number IN ( 2, 3 )
So on the first record, it is pointing to by it's own group to the T2 group AND the T2 group is specifically a 2... Then again, but testing the group for the T3 instance and T3's group is a 3.
If it cant complete the join to either of the T2 or T3 instances, the record is done for consideration, and since indexes work great for joins like this, make sure you have one index for your NUMBER criteria, and another index on the (GROUP, NUMBER) for those comparisons and the next query sample...
If doing by more than this simple 2, but larger group, prequery qualified groups, then join to that
select
YT2.*
from
( select YT1.group
from YourTable YT1
where YT1.Number in (2, 3)
group by YT1.group
having count( DISTINCT YT1.group ) = 2 ) PreQualified
JOIN YourTable YT2
on PreQualified.group = YT2.group
AND YT2.Number in (2,3)
Maybe this,if I understand you
SELECT id FROM table WHERE `group` IN
(SELECT `group` FROM table WHERE number IN (2,3)
GROUP BY `group`
HAVING COUNT(DISTINCT number)=2)
SQL Fiddle
This will return all ids where BOTH numbers exist in a group.Remove DISTINCT if you want ids for groups where just one numbers is in.

Complex sort and grouping with mysql

I have the ff table:
---------------------------
ID | ChapterNo | HitCount |
---------------------------
1 | 2 | 1000 |
2 | 2 | 2000 |
3 | 1 | 3000 |
4 | 3 | 1000 |
5 | 1 | 3500 |
---------------------------
Basically I need to archive this result:
Get all the unique chapterno where each have the highest hit count and then order by chapterno descending
ID | ChapterNo | HitCount |
---------------------------
4 | 3 | 1000 |
2 | 2 | 2000 |
5 | 1 | 3500 |
---------------------------
I tried the ff. query:
SELECT t1.*, Max(t1.hitcount) AS maxhit
FROM chapter as t1
GROUP BY t1.chapterno
ORDER BY t1.chapterno DESC
But some how it doesnt return the one with highest hitcount.
How can I fix this?
Thank you
SELECT t1.*, t1.hitcount AS maxhit
FROM chapter as t1
WHERE t1.hitcount = (select max(hitcount) from chapter where chapterno = t1.chapterno)
ORDER BY t1.chapterno DESC
SELECT t1.id, t1.chapterno, t2.maxhits
FROM chapter as t1,
(SELECT id, chapterno, Max(hitcount) AS maxhits
FROM chapter
GROUP BY chapterno) AS t2
WHERE t2.chapterno = t1.chapterno
AND t1.hitcount = t2.maxhits
ORDER BY t1.chapterno DESC
Try this one -
SELECT c1.id, c1.ChapterNo, c1.HitCount FROM chapter c1
JOIN (SELECT ChapterNo, MAX(HitCount) max_hitCount
FROM chapter
GROUP BY ChapterNo) c2
ON c1.ChapterNo = c2.ChapterNo AND c1.HitCount = c2.max_hitCount
ORDER BY c1.ChapterNo DESC;
SELECT t1.*, t1.hitcount AS maxhit
FROM chapter as t1
WHERE t1.hitcount = (
SELECT MAX t1.hitcount
from chapter as t2
where t2.ChapterNo = t1.chapterNo
)
ORDER BY t1.chapterno DESC
This uses a correlated subquery, which can become unefficient. Another possibility is to use an uncorrelated query in the from or left join.
More info on this article
although all above answers are perfect, i think it also can be done using SELF JOIN
SELECT *
FROM chapter ch
WHERE (
SELECT COUNT(*) FROM chapter ch2
WHERE ch2.chapterno = ch.chapterno and ch2.hitcount > ch.hitcount
) <= 2;