how to group_concat using distinct correctly - MYSQL - mysql

I have 3 table relation using MYSQL;
Example first as riders table:
bib | series_id | point
202 3 200
219 3 140
202 2 200
219 2 110
10 1 90
Example second as series table:
series_id | series_no | season_id
1 1 2
2 2 1
3 1 1
Example third as seasons table:
season_id | year
1 2015
2 2016
How to GROUP_CONCAT point correctly? I'm trying like this
SELECT riders.bib, seasons.year, GROUP_CONCAT(DISTINCT riders.point ORDER BY series.series_no DESC) AS seriPoint
FROM series, riders, seasons
GROUP BY riders.bib
I'm getting output seriPoint for bib: 202 is 200 and bib: 219 is 140,110 when I'm using DISTINCT output like that. But when I'm not using DISTINCT getting output seriPoint for bib: 202 is 200,200,200,200 and bib: 219 is 140,110,140,110. What I want is output seriPoint for bib: 202 is 200,200 and bib: 219 is 140,110.
ADD: please help to add filter too, for season_id when different season_id its to be different row.

yes you are getting correct output since you have used DISTINCT. BTW, you should change your query to use proper JOINS
SELECT riders.bib,
seasons.year,
GROUP_CONCAT(DISTINCT riders.point ORDER BY series.series_no DESC) AS seriPoint
FROM riders
JOIN series ON series.series_id = riders.series_id
JOIN seasons ON series.season_id = seasons.season_id
GROUP BY riders.bib;
(OR) you can get the grouping first and then perform join like
select seasons.year, xx.bib, xx.seriPoint
FROM series
JOIN (
select series_id, bib
group_concat(point) as seriPoint
from riders
group by bib ) xx ON series.series_id = xx.series_id
JOIN seasons ON series.season_id = seasons.season_id
order by xx.seriPoint;

Related

How to subtract one column from another column finding the previous occurrence of the same id?

I am working with the Sakila video rental database that comes preloaded with MySQL.
I am trying to find the average number of days each video sits on the shelf before it is rented again.
In the rentals table you have the rental_id for each rental transaction, the inventory_id corresponding to the item that was rented, as well as the rental_date and return_date.
For each rental transaction I would like to look at the rental_date and find the difference from the return_date of the previous occurrence of the same inventory_id.
I know LAG() and LEAD() might be useful here, but I have no idea how to make it only consider other rows with the same inventory_id.
Sample data:
rental_id inventory_id rental_date return_date
-------------------------------------------------------
1 115 01-01-2005 01-05-2005
2 209 01-01-2005 01-04-2005
3 115 01-06-2005 01-10-2005
4 209 01-09-2005 01-14-2005
5 209 01-15-2005 01-20-2005
6 115 01-16-2005 01-20-2005
Desired output:
rental_id inventory_id rental_date return_date days_on_shelf
------------------------------------------------------------------------
1 115 01-01-2005 01-05-2005 NULL
2 209 01-01-2005 01-04-2005 NULL
3 115 01-06-2005 01-10-2005 1
4 209 01-09-2005 01-14-2005 5
5 209 01-15-2005 01-20-2005 1
6 115 01-16-2005 01-20-2005 6
Thank you to June7. The correct code should look like this:
SELECT
rental.rental_id,
rental.inventory_id,
inventory.film_id,
rental.rental_date,
rental.return_date,
IF(#lastid = rental.inventory_id,
DATEDIFF(rental.rental_date, #lastreturn),
NULL) AS days_on_shelf,
#lastid:=rental.inventory_id,
#lastreturn:=rental.return_date
FROM
rental
JOIN
inventory ON rental.inventory_id = inventory.inventory_id
ORDER BY rental.inventory_id , rental.rental_date
You seem to just want lag():
select t.*,
datediff(rental_date,
lag(return_date) over (partition by inventory_id order by rental_date)
) as days_on_shelf
from t

SQL Problem regarding to get the sum of duplicate rows

This is my sql query to get the following table below :
select c.name, s.company, p.qty, p.qty * p.price as Total
from client c, purchase p, stock s
where c.clno = p.clno AND s.company = p.company
group by c.name, s.company, p.qty, p.qty * p.price
order by sum(p.qty) desc
The output of the above query looks like this :
Name | Company | Qty | Total
John ABC 12 100
Bob XYZ 10 150
John ABC 5 50
Bob XYZ 20 250
Bob XYZ 2 20
Nav QRS 10 150
John ABC 10 150
I want to have the query to get the output as the following :
Name | Company | Qty | Total
John ABC 27 300
Bob XYZ 32 420
Nav QRS 10 150
As of now your query uses GROUP BY but does not actually aggregates data. You want to GROUP BY name and company, and SUM the quantities and amounts, like :
select c.name, s.company, SUM(p.qty), SUM(p.qty * p.price) as Total
from client c
inner join purchase p on c.clno = p.clno
inner join stock s on s.company = p.company
group by c.name, s.company
order by Total desc
Other remarks regarding your query :
always use explicit joins instead of implicit ones
you can use column aliases in the ORDER BY clause (here, Total ; this can make the query easier to read

Join two tables using mysql

table:tab1
id date_time zoneid accountid slotid trequest bidder width height
_50832 2017-09-04 15:41:06 153 1654 153x468x60 10 aaa 468 60
_50832 2017-09-04 15:41:06 152 1654 152x468x60 10 bbb 468 60
table:tab2
id date_time zoneid accountid slotid bidder count
_50832 2017-09-04 15:41:06 152 1654 152x468x60 bbb 6
_50832 2017-09-04 15:41:06 152 1654 152x468x60 bbb 4
_50832 2017-09-04 15:41:06 153 1654 153x468x60 aaa 9
_50832 2017-09-04 15:41:06 153 1654 153x468x60 aaa 1
below is my query:
SELECT SUM(req.trequest) as REQ, SUM(win.count) as IMP
FROM tab1 as req
JOIN tab2 as win ON (req.id=win.id AND req.zoneid=win.zoneid)
GROUP BY req.zoneid
I get below result,
REQ IMP
20 10
20 10
IMP count is correct but I get wrong REQ count. My expected result is
REQ IMP
10 10
10 10
How to get my expected result?
Lets find the sum of trequest and count separately based on zoneid and id.Then use these two results ( t1 and t2 ) in the inner join.
Count mismatch problem shown in the question occur due to multiple rows satisfying the joining conditions.
In this solution we will only have one entry for each zoneid in both the results ( t1 and t2 ). So the problem is avoided.
Note: You can remove the id column from the GROUP BY clause if it doesn't make any difference.
SELECT t1.id, t1.zoneid, t1.REQ, t2.IMP FROM
(SELECT id,zoneid,SUM(trequest) as REQ
FROM tab1 GROUP BY zoneid,id ) t1
INNER JOIN
(SELECT id,zoneid SUM(win.count) as IMP
FROM tab2 GROUP BY zoneid,id ) t2
ON t1.id = t2.id
AND t1.zoneid = t2.zoneid
Let's try first sumwin.count and group records in sub-query, after it join tables. Try in following:
SELECT SUM(req.trequest) as REQ, SUM(win.count) as IMP
FROM tab1 as req
JOIN (
SELECT SUM(win.count) as IMP, win.zoneid, win.id
FROM tab2 as win
GROUP BY win.zoneid, win.id) AS win ON req.id=win.id AND req.zoneid=win.zoneid
GROUP BY req.zoneid
Instead of req.zoneid. You should try win.zoneid. What seems is that the rows in table 1 are counted multiple times as zoneid in table 2 comes twice. So win.zoneid would group it and avoid the repetition.
Updated: The solution posted by #mayur panchal is the correct one as you don't need to SUM the rows in first table as they belong to different zoneid. If you SUM them you will obviously get the 20 repeated twice.

Sum values in mysql table where userid is identical

I have read the different answers here on SO, but I am stuck on this question. Please help.
I have this mysql view named "activeuser":
userid COUNT(*) ACRONYM
1 23 admin
2 2 doe
3 4 tompa
12 4 Marre
13 1 Mia
1 2 admin
3 1 tompa
12 1 Marre
13 1 Mia
2 1 doe
3 1 tompa
12 1 Marre
How can I sum the COUNT column so that I get the following wanted result?
userid COUNT(*) ACRONYM
1 25 admin
2 3 doe
3 6 tompa
12 6 Marre
13 1 Mia
EDITED:
I used this query to create the view:
CREATE VIEW activeuser AS
(SELECT boats_comments.userid, COUNT(boats_comments.userid), boats_user.acronym, boats_user.email
FROM boats_comments
INNER JOIN boats_user
ON boats_comments.userid = boats_user.id
GROUP BY boats_comments.userid
ORDER BY COUNT(boats_comments.userid) DESC)
UNION ALL
(SELECT boats_answers.userid, COUNT(boats_answers.userid), boats_user.acronym, boats_user.email
FROM boats_answers
INNER JOIN boats_user
ON boats_answers.userid = boats_user.id
GROUP BY boats_answers.userid
ORDER BY COUNT(boats_answers.userid) DESC)
UNION ALL
(SELECT boats_questions.userid, COUNT(boats_questions.userid), boats_user.acronym, boats_user.email
FROM boats_questions
INNER JOIN boats_user
ON boats_questions.userid = boats_user.id
GROUP BY boats_questions.userid
ORDER BY COUNT(boats_questions.userid) DESC)
My goal is to see which users are the most active by checking the number of comments, questions and answers... but I got stuck...
As the results in your view has duplicates I guess the underlying code for the view is grouping on something it maybe shouldn't be grouping on.
You can get the results you want by applying SUM to it:
select userid, sum("whatever column2 is named") as "Count", Acronym
from activeuser group by userid, Acronym;
select userid, count(*) from activeuser group by userid;

Group by various column (with various joins) but sum distinct other column

I have to do some reporting, involving various tables, and having couple of SUMs, COUNTs, etc and everything is OK. But the last thing I have to resolve is SUM by another which is not in the grouped columns.
I'll give you an example (stripped down from what I have) so you can understand the tongue-twister in the previous paragraph.
Suppose I have a query with a couple of joins that get me this result, or a temporary table, or whatever:
(this is a trimmed down version, in the original I have much more columns and groupbys)
APP_ID CAT_ID CAT_DESCRIP APP_START APP_END DETAIL_ID DET_QTY DETAIL_PRICE
1 1 Categ One 900 960 1 10 150.00
1 1 Categ One 900 960 2 8 20.00
1 1 Categ One 900 960 3 12 30.00
1 1 Categ One 900 960 4 5 100.00
2 2 Categ Two 600 720 5 12 150.00
2 2 Categ Two 600 720 6 10 50.00
3 2 Categ Two 1200 1260 7 5 20.00
I need to get something like this: (the bolded column is the important)
SELECT
CAT_ID,
CAT_DESCRIP,
SUM(DET_QTY) as TotalQTY,
SUM(DETAIL_PRICE) as TotalPrice,
COUNT(DISTINCT APP_ID) as CountOfApps,
(GET THE SUM OF (APP_END - APP_START) ONLY ONE TIME BY APP_ID INTO THIS CATEG) as TimeInMinutesByCategory
FROM
MyTable
GROUP BY
CAT_ID
And the result has to give me this:
CAT_ID CAT_DESCRIP TotalQTY TotalPrice CountOfApps TimeInMinutesByCategory
1 Categ One 35 300.00 1 60
2 Categ Two 27 220.00 2 180
Thanks for your help!
I think this will do the job... or if not, a little tweaking on the sytnax for max(app_start) - max(app_end) should do the job
The idea is, summarize the data in a subquery by app_id and cat_id. Select the max value of start and end, grouped by app_id and cat_id. Since there will only be one value per each distinct pair of app_id and cat_id, we're essentially just deduping.
Then, join the subquery to the main query and summarize by category id.
SELECT
a.CAT_ID,
a.CAT_DESCRIP,
SUM(a.DET_QTY) as TotalQTY,
SUM(a.DETAIL_PRICE) as TotalPrice,
COUNT(DISTINCT a.APP_ID) as CountOfApps,
SUM(b.TimeInMinutesByCategory) AS TimeInMinutesByCategory
FROM
MyTable AS a
INNER JOIN (
SELECT APP_ID, CAT_ID, max(app_start) - max(app_end) AS TimeInMinutesByCategory
FROM MyTable
GROUP BY APP_ID, CAT_ID) AS b
ON a.cat_id = b.cat_id
AND a.app_id = b.app_id
GROUP BY
a.CAT_ID