GROUP BY id showing newest entry of same ID - mysql

I know this has already been asked answered a thousend times. But I seem not to be able to resolve this.
I am trying to group by and order this query so I can join it as subquery to a bigger query
SELECT * FROM `ggorderlog`
WHERE `GGTITLE` LIKE '%Reklamation%'
ORDER BY `GGDATE` DESC, `ggorderlog`.`GGORDERID` DESC
This is the result from the ggorderlog table and the query above
GGTITLE GGOXID GGDATE GGORDERID GGTITLE User
Reklamation uniqueid1 2018.12.7 16:20:00 1 Reklamation created Max Mustermann
Reklamation uniqueid2 2018.12.7 16:24:00 1 Reklamation finished Maxine Musterfrau
Reklamation uniqueid3 2018.12.7 16:22:00 2 Reklamation created Max mustermann
Now what I want is to have this table be displayed so that for every GGORDERID I only see the latest entry. In order to give an overview over the User who has worked on this and the status of the ticket.
Like this:
GGTITLE GGOXID GGDATE GGORDERID GGTITLE User
Reklamation uniqueid2 2018.12.7 16:24:00 1 Reklamation finished Maxine Musterfrau
Reklamation uniqueid3 2018.12.7 16:22:00 2 Reklamation created Max mustermann
I tried standard group by with order by but mysql seem to do the group by first and give out a random column
I tried this but it still shows always a random date.
Select* from (
Select *
from ggorderlog as b
where GGTITLE like '%Reklamation%'
ORDER BY b.GGDATE DESC
) b2
group by b2.GGORDERID
I tried a lot of other suggestions with left itselfe or group_concat and then desolve again but nothing seems to work.

Can you try this ?
SELECT gg.*
FROM ggorderlog gg
INNER JOIN
(SELECT ggorderid, MAX(ggdate) AS maxggdate,oxid
FROM ggorderlog
GROUP BY ggorderid) groupedgg
ON gg.oxid = groupedgg.oxid
AND gg.ggdate = groupedgg.maxggdate

Related

Having an issue with displaying most recent Call_date

I am trying to output the most recent Call_date. I have tried using the MAX function with no luck. Below I have tagged 3 images showing the database tables, my current code output and the required output. Underneath that is my current code. Any help is appreciated!
Database Tables - https://imgur.com/a/7ZPFO
Output we are looking for - https://imgur.com/a/k3idB
Output my code currently gives - https://imgur.com/a/H53vq
Here is what I have tried:
SELECT Staff.First_name, Staff.Last_name, call_date, taken_by
FROM Issue
JOIN Caller ON Issue.Caller_id = Caller.Caller_id
JOIN Staff ON Issue.Taken_by = Staff.Staff_code
WHERE Caller.First_name = 'Harry'
I would just add the following to the end of your query:
ORDER BY call_date DESC LIMIT 1
This will give you one row as a result. And that row will be the one with the most recent call_date.
Based on the code provided, you're only asking for 3 columns so it's a matter of a join. When you select the max call date you need to group by the other 2 non-aggregate columns. If the date column is of datatype Date or Datetime then this should work:
SELECT Caller.First_name, Caller.Last_name --from Caller_id
,MAX(Issue.call_date) AS call_date
FROM Issue INNER JOIN Caller ON Issue.Caller_id = Caller.Caller_id
WHERE Caller.First_name = 'Harry'
GROUP BY Caller.First_name, Caller.Last_name

how to I select records based on the latest date

I am trying to get the latest record only. It works fine if i don't include "CustFile.optin" but once I add this field, it gives me all the records. Can you please help?
SELECT BEST.fname, BEST.lname, BEST.email, MAX(CustFile.status_date), CustFile.optin
FROM BEST, CustFile
WHERE BEST.email = CustFile.email
GROUP BY BEST.fname, BEST.lname, BEST.email, CustFile.optin
Answer:
fname lname email optin date
a.fname a.lname aa#email y 01/08/2015
b.fname b.lname bb#email n 16/06/2016
Why not simply take the row WHERE MAX(CustFile.status_date) = CustFile.status_date?
SELECT *
FROM BEST, CustFile
WHERE
BEST.email = CustFile.email AND
MAX(CustFile.status_date) = CustFile.status_date
Or order by date (desc) and take only the top most as #Paul-Spiegel says
SELECT *
FROM BEST, CustFile
WHERE BEST.email = CustFile.email
ORDER BY status_date DESC
LIMIT 1

MySQL MAX from count query

I have table rozpis_riesitelov which contains columns :
id_rozpisu_riesit, id_zam, id_projektu, id_ulohy.
I made query :
select id_zam, id_ulohy, count(*) as counted
from rozpis_riesitelov
group by id_zam
having id_ulohy in (1,2,8)
which shows me id of employee (id_zam) and how many times He was in project (id_ulohy is irrevelant but I had to select it beacuse of having clause). It shows me everyone in db but I am looking for employee with ID of 4 who is in 6 projects (Yes, I could do order by but I want to see max). When I do max of this query like this:
select max(counted)
from (select id_zam, id_ulohy, count(id_zam) as counted
from rozpis_riesitelov
group by id_zam
having id_ulohy in (1,2,8)) as riesitel
which shows me number 149 instead of 6.
So basically I only need to find employee that occurs in the most of the projects.
What's wrong with sorting by the COUNT() value, and limiting to one result?
SELECT `id_zam`,
`id_ulohy`,
COUNT(*) AS `counted`
FROM `rozpis_riesitelov `
WHERE `id_ulohy` IN ( 1, 2, 8 )
GROUP BY `id_zam`
ORDER BY `counted` DESC
LIMIT 1
Not sure exactly what you are trying to accomplish but you only use HAVING to filter on your aggregate like this:
HAVING COUNT(*) > 1
you should be able to move the condition to a WHERE clause and get correct max returned:
select max(counted)
from (select id_zam, count(id_zam) as counted
from rozpis_riesitelov
where id_ulohy in (1,2,8)
group by id_zam) as riesitel

Need help to make one mysql query to get expected result for my requirement

I am facing few issue to write mysql query in my scope to get result. Actually I am getting appropriate result using this existing query but it is not written appropriate way. Here is my query:
SELECT c.ID, c.chn_name,c.chn_logo,
(SELECT ID FROM tv_showtime WHERE showtime<='2013-02-18 10:28:35' AND status='Enable' AND chn_id=c.ID ORDER BY ID DESC Limit 0,1) as currentshowid,
(SELECT tv_showtime FROM tv_showtime WHERE showtime<='2013-02-18 10:28:35' AND status='Enable' AND chn_id=c.ID ORDER BY ID DESC Limit 0,1) as currentshowtime ,
(SELECT tv_showtime FROM tv_showtime WHERE showtime >'2013-02-18 10:28:35' AND status='Enable' AND chn_id=c.ID ORDER BY ID ASC Limit 0,1) as nextshowtime
FROM tv_channels AS c
WHERE c.status="Enable"
ORDER BY c.chn_name
LIMIT 0,10
Here, there are only two tables named as "tv_channels" and "tv_showtime". I need one record for each channel at a time ( for current time). So here suppose 12 channels and approx 30 (may vary foe each channel) records for each channel and I only need to display channels with current show (More clarification: only channels will be displayed which has current show time and/or next show time.)
Problem: I need more field values from "tv_showtime" to display other required values. And if I will use this way then I have to write more inner select query and it will slow down my website to load. So can you suggest or advise any other way to write this query please?
Database table detail:
tv_channels [ID, chn_name, [other required fields]],
tv_showtime [ID, chn_id, showtime, show_name, hits, last_ip [and few more fields]]
Please let me know if you will need further detail to get this question.
Any help or suggestion will be appreciated. thanks.
As another asked, but you didnt respond to an "end time" for each show, I had to go on the premise that the show time was when it started. That said, how do you determine which is the current show running for a given channel based on CURTIME() (instead of fixed time value).
Get each channel and the MAXIMUM SHOW Time that exists PRIOR TO the current time...
Likewise, how to get the NEXT Show? Get each channel with the MINIMUM SHOW time that STARTS AFTER the current time.
So, if I had the following records for 1 channels and the current time is 2:15pm
Channel ShowTime Show_Name
1 12:30pm Show "X"
1 01:00pm Show "B"
1 01:30pm Show "C"
1 02:00pm Show "D" <- Current Show
1 02:30pm Show "Y" <- Next Show
1 03:00pm Show "Z"
The current show running is the latest one PRIOR to 2:15 (Show "D" starting at 2pm)
and the NEXT Show is first AFTER current time (Show "Y" starting at 2:30pm). The above will work even if the rows are not in sequential order as I am using MIN() and MAX() respectively to get the time.
So, I start with the channel table and do a left-join to each separate pre-aggregate query for detecting the current show and next show times respectively and join on the channel ID which each COULD return at most one record --- provided there IS a record within qualified WHERE CURTIME() consideration.
From THAT, I am re-joining THOSE result sets back to the actual tv schedule table AGAIN, but this time, on the channel AND the time that matched the corresponding current or next time.
So now, I have everything lined up ready to go with respective aliases for content. Now, I just grab the columns I want to present.
Since the joins are all LEFT-JOINs, each side COULD have NULL values, so you might want to adjust the query to prevent nulls using COALESCE(), such as I've sampled...
SELECT
TC.ID,
TC.Chn_Name,
TC.Chn_Logo,
COALESCE( CurShowTimeDetail.ShowTime, 'no time' ) CurShowTime,
COALESCE( CurShowTimeDetail.Show_Name, '' ) CurShowName,
COALESCE( CurShowTimeDetail.Hits, 0 ) CurHits,
COALESCE( NextShowTimeDetail.ShowTime, 'no time' ) NextShowTime,
COALESCE( NextShowTimeDetail.Show_Name, '' ) NextShowName,
COALESCE( NextShowTimeDetail.Hits, 0 ) NextHits
from
TV_Channels TC
LEFT JOIN ( SELECT
ST.chn_id,
MAX( ST.showtime ) CurShowTime
from
tv_showtime ST
where
ST.ShowTime < CURTIME()
group by
ST.chn_id ) CurrentShow
ON TC.ID = CurrentShow.Chn_ID
LEFT JOIN tv_showtime CurShowTimeDetail
ON CurrentShow.Chn_ID = CurShowTimeDetail.Chn_ID
AND CurrentShow.CurShowTime = CurShowTimeDetail.ShowTime
LEFT JOIN ( SELECT
ST.chn_id,
MIN( ST.showtime ) NextShowTime
from
tv_showtime ST
where
ST.ShowTime > CURTIME()
group by
ST.chn_id ) NextShow
ON TC.ID = NextShow.Chn_ID
LEFT JOIN tv_showtime NextShowTimeDetail
ON NextShow.Chn_ID = NextShowTimeDetail.Chn_ID
AND NextShow.NextShowTime = NextShowTimeDetail.ShowTime
To select last (first) records from a table by some order, you may LEFT JOIN the table with itself as any next (previous) element, and add a condition that there is no such element.
SELECT c.ID, c.chn_name, c.chn_logo
, curr_sh.ID AS currentshowid, curr_sh.showtime AS currentshowtime -- Continue with desired columns
, next_sh.showtime AS nextshowtime -- Continue with desired columns
FROM tv_channels AS c
LEFT JOIN tv_showtime AS curr_sh
ON curr_sh.chn_id = c.ID
AND curr_sh.showtime <= '2013-02-18 10:28:35'
AND curr_sh.status='Enable'
LEFT JOIN tv_showtime AS curr_next_sh
ON curr_next_sh.chn_id = curr_sh.chn_id
AND curr_next_sh.showtime > curr_sh.showtime
AND curr_next_sh.showtime <= '2013-02-18 10:28:35'
AND curr_next_sh.status = 'Enable'
LEFT JOIN tv_showtime AS next_sh
ON next_sh.chn_id = c.ID
AND next_sh.showtime > '2013-02-18 10:28:35'
AND next_sh.status='Enable'
LEFT JOIN tv_showtime AS next_prev_sh
ON next_prev_sh.chn_id = next_sh.chn_id
AND next_prev_sh.showtime < next_sh.showtime
AND next_prev_sh.showtime > '2013-02-18 10:28:35'
AND next_prev_sh.status = 'Enable'
WHERE c.status = 'Enable'
AND curr_next_sh.ID IS NULL -- This gives us only the latest current show
AND next_prev_sh.ID IS NULL -- This gives us only the earliest next show
AND (curr_sh.ID IS NOT NULL OR next_sh.ID IS NOT NULL) -- This gives us 'which has current show time and/or next show time'
ORDER BY c.chn_name
LIMIT 0,10
But I'm not sure about performance, and whether this solution is optimal.

Join Two tables multiple times

I need result from two tables , where one is parent table and other is child table as well as parent table it self for sub level child entries.
if i do the sql query like:
SELECT cc.collection_id, cc.title, cc.type, cc.alias as forum_alias,
SUBSTRING(cc.description,1,200) as short_desc,
COUNT(b1.boardmessage_id) as total_threads,
COUNT(b2.boardmessage_id) as total_replies
FROM contentcollections cc
JOIN boardmessages b1 ON b1.parent_id = cc.collection_id
JOIN boardmessages b2 ON b2.collection_id = cc.collection_id
WHERE cc.type=1
AND cc.is_active=1
AND b1.parent_type='collection'
AND b1.is_active=1
AND b2.parent_type IN('message','reply','reply_on_reply')
GROUP BY cc.collection_id
ORDER BY cc.created DESC;
it gives me the wrong out put with same number of total threads and same number of total replies.How ever if i do something like this
SELECT cc.collection_id, cc.title,cc.type, cc.alias as forum_alias,
SUBSTRING(cc.description,1,200) as short_desc,
(SELECT COUNT(boardmessage_id)
FROM boardmessages
WHERE parent_type='collection'
AND collection_id=cc.collection_id
AND is_active=1) as total_threads,
(SELECT count(boardmessage_id)
FROM boardmessages
WHERE parent_type IN('message','reply','reply_on_reply')
AND collection_id=cc.collection_id AND is_active=1) as total_replies
FROM contentcollections cc
WHERE cc.type=? AND cc.is_active=?
ORDER BY cc.created DESC
It gives me the correct answer.
I suspect i am using sub queries in the second option so it may slow down the performance of the page rendering.
Please suggest me for the same.Any help or suggestion would be greatly appreciated.
Thanks
Replace:
COUNT(b1.boardmessage_id) as total_threads,
COUNT(b2.boardmessage_id) as total_replies
With:
COUNT(DISTINCT b1.boardmessage_id) as total_threads,
COUNT(DISTINCT b2.boardmessage_id) as total_replies
if you only want each row to count once, instead of the default, counting all combinations.
If you have 3 rows in b1 and 5 rows in b2, you get a total of 15 rows, and both counts return that there are 15 rows, with the distinct flag you get the answers 3 and 5 instead, as its 3 distinct values in b1, and 5 distinct values in b2.