How to get count for each row mysql query? - mysql

I have Three tables
1)review_trans
2)user_comment_trans
3)helpful_review_trans
The table structure looks like this
review_trans
review_id(pk) | review_desc | user_id
--------------+----------------+-----------
1 | hello world | 1
2 | test2 | 1
3 | test3 | 2
user_comment_trans
comment_id | review_id | user_id
------------+--------------+------------
1 | 1 | 4
2 | 1 | 2
3 | 2 | 3
helpful_review_trans
helpful_review_id | review_id | user_id
------------------+------------+------------
1 | 1 | 4
2 | 1 | 2
3 | 2 | 3
I want count on each review for helpful votes and comments.
So output i want is like this
OUTPUT
review_id review_desc count(helpful_review_id) count(comment_id)
------------+------------------+----------------------------+--------------------
1 | hello world | 2 | 2
2 | test2 | 1 | 1
3 | test3 | |
Iam unable to get this record.I tried joining the tables but it only shows just one review_desc
Please advise and help.

Use left join with count(distinct)
select r.review_id,
r.review_desc,
count(distinct u.comment_id),
count(distinct h.helpful_review_id)
from review_trans r
left join user_comment_trans u on(r.review_id = u.review_id)
left join helpful_review_trans h on(r.review_id = h.review_id)
group by r.review_id
Demo

SELECT rt.review_id, rt.review_desc,
COUNT(DISTINCT hrt.helpful_review_id), COUNT(DISTINCT uct.comment_id)
FROM review_trans rt
LEFT JOIN helpful_review_trans hrt ON rt.review_id = hrt.review_id
LEFT JOIN user_comment_trans uct ON uct.review_id = rt.review_id
GROUP BY rt.review_id

SELECT rt.review_id, rt.review_desc, helpful_count, comment_count
FROM review_trans AS rt
LEFT JOIN (
SELECT review_id, COUNT(*) AS comment_count
FROM user_comment_trans
GROUP BY review_id) AS uct ON rt.review_id = uct.review_id
LEFT JOIN (
SELECT review_id, COUNT(*) AS helpful_count
FROM helpful_review_trans
GROUP BY review_id) AS hrt ON rt.review_id = hrt.review_id

You could do this:
SELECT
review_trans.review_id,
review_trans.review_desc,
(
SELECT
COUNT(*)
FROM
helpful_review_trans
WHERE
helpful_review_trans.review_id=review_trans.review_id
) AS helpful_review_id,
(
SELECT
COUNT(*)
FROM
user_comment_trans
WHERE
user_comment_trans.review_id=review_trans.review_id
) AS CountComment_id
FROM
review_trans

Related

How to join 5 tables MYSQL with specific condition

i have 5 tables below
tb_satker
kdsatker
1
2
3
tb_akun
akun | code
A | 1
B | 2
C | 3
tb_simponi
kdsatker | akun | jumlah
1 | A | 100
1 | B | 200
tb_span
kdsatker | akun | jumlah
1 | A | 1
1 | B | 2
1 | C | 3
tb_upt
kdsatker | akun | jumlah
1 | A | 10
1 | B | 20
1 | C | 30
What i need is output to something like this
kdsatker | akun | simponi | span | upt
1 | A | 100 | 1 | 10
1 | B | 200 | 2 | 20
1 | C | 0 | 3 | 30
2 | 0 | 0 | 0 | 0
3 | 0 | 0 | 0 | 0
I've try using sql fiddle but the result is not right (http://sqlfiddle.com/#!9/e83ce7/10)
SELECT tb_satker.kdsatker,tb_akun.akun,tb_simponi2.simponi,tb_span2.span,tb_upt2.upt
FROM tb_satker
LEFT JOIN (SELECT kdsatker,akun,sum(tb_simponi.jumlah) as simponi FROM tb_simponi GROUP BY kdsatker,akun)
as tb_simponi2 ON tb_simponi2.kdsatker=tb_satker.kdsatker
LEFT JOIN (SELECT kdsatker,akun,sum(tb_span.jumlah) as span FROM tb_span GROUP BY kdsatker,akun)
as tb_span2 ON tb_span2.kdsatker=tb_satker.kdsatker
LEFT JOIN (SELECT kdsatker,akun,sum(tb_upt.jumlah) as upt FROM tb_upt GROUP BY kdsatker,akun)
as tb_upt2 ON tb_upt2.kdsatker=tb_satker.kdsatker
LEFT JOIN
tb_akun ON tb_akun.akun=tb_simponi2.akun AND
tb_akun.akun=tb_span2.akun AND
tb_akun.akun=tb_upt2.akun
GROUP BY tb_satker.kdsatker,tb_akun.akun
Can anybody help me with the right idea??
Many Thanks
Your inner queries are all based on a two-part group by two parts... kdsatker and akun.
Since it is possible for any of the tb_simponi, tb_span, tb_upt can have any combination,
I would pre-union all possible combinations of those FIRST. THEN, Join to the summary results.
and FINALLY get the akun and kdsatker components. Something like...
SELECT
tb_satker.kdsatker,
coalesce( tb_akun.akun, 0 ) akun,
coalesce( tb_simponi2.simponi, 0 ) simponi,
coalesce( tb_span2.span, 0 ) span,
coalesce( tb_upt2.upt, 0 ) upt
FROM
tb_satker
LEFT JOIN
( SELECT distinct kdsatker, akun FROM tb_simponi
UNION
SELECT kdsatker, akun FROM tb_span
UNION
SELECT kdsatker, akun FROM tb_upt
) AllKdAkun
on tb_satker.kdsatker = AllKdAkun.kdsatker
LEFT JOIN tb_akun
on AllKdAkun.akun = tb_akun.akun
LEFT JOIN
(SELECT kdsatker, akun, sum(tb_simponi.jumlah) as simponi
FROM tb_simponi
GROUP BY kdsatker, akun ) as tb_simponi2
ON AllKdAkun.kdsatker = tb_simponi2.kdsatker
AND AllKdAkun.Akun = tb_simponi2.akun
LEFT JOIN
(SELECT kdsatker, akun, sum(tb_span.jumlah) as span
FROM tb_span
GROUP BY kdsatker, akun ) as tb_span2
ON AllKdAkun.kdsatker = tb_span2.kdsatker
AND AllKdAkun.akun = tb_span2.akun
LEFT JOIN
(SELECT kdsatker, akun, sum(tb_upt.jumlah) as upt
FROM tb_upt
GROUP BY kdsatker, akun) as tb_upt2
ON AllKdAkun.kdsatker = tb_upt2.kdsatker
AND AllKdAkun.akun = tb_upt2.akun
No final group by at the outer level.
First level is your tb_satker. There may (or not) be a record in any of the subsidiary tables, so that is first.
Second level is a distinct list of every kdsatker, akun in ANY of the other 3 tables. So now you can LEFT JOIN kdsatker thus keeping every record including 1, 2, 3 even though 2 & 3 have no records.
From the second level, you can now left-join to the tb_akun table which in this case, only kdsatker is the only one with records for any given akun.
Finally joining the pre-union list of all combinations grouped by kdsatker, akun are able to be matched for their final summary into the final list.
Hope each step makes sense to what you appear to be trying for.

Select last record of each person

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.

Mysql query inner join two tables with group by last ID

I'm using two tables in the database:
The "members" table:
id | name
-----------------------
1 | John
2 | Mike
3 | Jane
4 | Marry
The "messages" table:
message_id | text | from | to
---------------------------------------------
1 | text 1 | 1 | 2
2 | text 2 | 1 | 3
3 | text 3 | 1 | 4
4 | text 4 | 2 | 1
5 | text 5 | 1 | 2
I need to get as a result grouped messages sent by a specific user, sorted by the last message sent and count the total number of sent messages to specific user.
My current mysql query looks:
SELECT max(messages.message_id) as max_mess, messages.from, messages.to, members.name, messages.text
FROM messages INNER JOIN members on members.id = messages.to
WHERE messages.from = '1'
GROUP BY messages.from
ORDER BY max_mess DESC
Required result should look like:
max_mess | from | to | name | text | total_messages
--------------------------------------------------------------------
5 | 1 | 2 | Mike | text 5 | 3
3 | 1 | 4 | Marry | text 3 | 1
2 | 1 | 3 | Jane | text 2 | 1
Is it possible to do that using only one mysql query and what should be changed in the current query?
You can use one of the following solutions:
solution #1 (using a additional JOIN):
SELECT
m1.max_mess,
m1.from,
m1.to,
m1.name,
m2.text,
m1.total_messages
FROM (
SELECT
MAX(message_id) AS max_mess,
messages.from,
messages.to,
members.name,
COUNT(message_id) AS total_messages
FROM messages INNER JOIN members ON members.id = messages.to
WHERE messages.from = 1
GROUP BY messages.from, messages.to
) m1 LEFT JOIN messages m2 ON m1.max_mess = m2.message_id
ORDER BY m1.max_mess DESC;
demo: http://sqlfiddle.com/#!9/7c73b6/1/0
Note: This solution should be faster than the second solution. You can find more details on the following answer on StackOverflow: JOIN vs. Sub-Query.
solution #2 (using a sub-select):
SELECT
MAX(message_id) AS max_mess,
m1.from,
m1.to,
members.name,
(SELECT messages.text FROM messages WHERE message_id = MAX(m1.message_id)) as text,
COUNT(message_id) AS total_messages
FROM messages m1 INNER JOIN members ON members.id = m1.to
WHERE m1.from = 1
GROUP BY m1.from, m1.to
ORDER BY max_mess DESC;
demo: http://sqlfiddle.com/#!9/7c73b6/2/0
This is one query. If you want to remove the JOIN statement then you should use
SELECT max(messages.message_id) as max_mess, messages.from, messages.to, members.name, messages.text
FROM messages, members
WHERE messages.from = '1' AND members.id = messages.to
GROUP BY messages.from
ORDER BY max_mess DESC
i think you are searching for this:
SELECT MAX(messages.message_id) AS max_mess, messages.from, messages.to, members.name, messages.text,, SUM(`from`) total_messages
FROM messages INNER JOIN members ON members.id = messages.to
WHERE messages.from = '1'
GROUP BY messages.from,messages.to
ORDER BY max_mess DESC;

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

getting latest data in one to many relation table

i would like to fetch data from table a,b,c but order by most recent data of table response
table casework has this structure ( simplified):
casework_id | problem | user_id
------------+-----------+-------
1 | Problem1 | 1
2 | Problem2 | 2
3 | Problem3 | 1
4 | Problem4 | 3
table user has this structure ( simplified):
user_id | name
--------+-----------------
1 | peter
2 | Sam
3 | Tom
4 | Steve
table response has this structure ( simplified):
response_id | response | casework_id | created
------------+-----------+--------------+-------
1 | responce1 | 1 | 2012-10-14 11:28:31
2 | responce2 | 1 | 2012-9-10 11:28:31
3 | responce3 | 1 | 2012-9-2 11:28:31
4 | responce4 | 3 | 2012-8-3 11:28:31
4 | responce5 | 3 | 2012-8-2 11:28:31
I am looking the query to fetch data order by latest responce and group by casework_id
I. e. required out put is
casework_id | problem | name | responce | created
------------+-----------+-------+-----------+---------
1 | Problem1 | peter | responce1 | 2012-10-14 11:28:31
2 | Problem2 | Sam | Null | Null
3 | Problem3 | peter | responce4 | 2012-8-3 11:28:31
4 | Problem4 | Tom | Null | Null
I would be most grateful if one of you kind people could point me in the right direction.
You can use the following:
select c.casework_id,
c.problem,
u.name,
r2.response,
r1.created
from casework c
left join user u
on c.user_id = u.user_id
left join
(
select max(created) created, casework_id
from response r
group by casework_id
) r1
on c.casework_id = r1.casework_id
left join response r2
on r1.created = r2.created
and r1.casework_id = r2.casework_id
See SQL Fiddle with Demo
If you want to include both the user that created the casework and then who responsed, then you will want to join on the user table twice:
select c.casework_id,
c.problem,
u1.name CreatedByName,
r2.response,
r1.created,
u2.name ReponseName
from casework c
left join user u1
on c.user_id = u1.user_id
left join
(
select max(created) created, casework_id
from response r
group by casework_id
) r1
on c.casework_id = r1.casework_id
left join response r2
on r1.created = r2.created
and r1.casework_id = r2.casework_id
left join user u2
on r2.user_id = u2.user_id
See SQL Fiddle with demo
I have not tested it, but it might give you an idea
select c.casework_id, c.problem,
(select name from user u where u.user_id = c.user_id ),
(select r.reponse from response r where r.casework_id = c.casework_id ORDER BY r.created DESC LIMIT 1),
(select r.created from response r where r.casework_id = c.casework_id ORDER BY r.created DESC LIMIT 1),
from casework c
SELECT responce.casework_id, problem, name, responce, created
FROM responce
JOIN
(SELECT casework_id, problem, name
FROM casework JOIN user
ON casework.userid=user.userid) AS A
ON responce.casework_id=A.casework_id
ORDER BY responce, responce.casework_id
Try this
select c.caseword_id, c.problem, u.name, response.response, responce.created from asework c inner join user u on u.user_id = c.user_id left outer join select casework_id from response having max(created) group by casework_id) responsedata on responsedata.casework_id = c.casework_id