Each page in my system has multiple page_objects.
I need to return the last_changed records of my page_objects per page.
To decrease DB-impact, I have a SELECT ... IN query to return each last-edited page_object per page:
SELECT object, f_page_id, page_object_id, last_change
FROM page_objects
WHERE f_page_id IN (page_id1, page_id2, page_id3, etc...) GROUP BY f_page_id
ORDER BY last_change ASC;
Of course this does not work, because GROUP BY is applied before ORDER BY, so I changed the query:
SELECT object, f_page_id, page_object_id, max(UNIX_TIMESTAMP(last_change))
FROM page_objects
WHERE f_page_id IN (page_id1, page_id2, page_id3, etc...) GROUP BY f_page_id
But this still does not return the last-edited page_object per page_id.
What am I doing wrong?
Your query does not specify to get the record for the latest last_change. Merely that it gets the latest value of last_change. The other non aggregate values (ie, not the result of an aggregate function like MAX or MIN) that are not mentioned in the GROUP BY clause can come from any row for the grouped values.
As such you use a sub query to get the latest value for each page, and then join that back against your main table to get the matching rows
Something like this:-
SELECT page_objects.object,
page_objects.f_page_id,
page_objects.page_object_id,
page_objects.last_change
FROM page_objects
INNER JOIN
(
SELECT f_page_id, MAX(last_change) AS latest_last_change
FROM page_objects
GROUP BY f_page_id
) sub0
ON page_objects.f_page_id = sub0.f_page_id
AND page_objects.last_change = sub0.latest_last_change
WHERE page_objects.f_page_id IN (page_id1, page_id2, page_id3, etc...)
ORDER BY last_change DESC
Note that MySQL is quite unusual at allowing you to have non aggregate columns that are not mentioned in the GROUP BY clause (as it is against SQL standards, except under very particular circumstances). Most flavours of SQL will issue an error if you try this, and MySQL has a configuration parameter which will similar cause it to reject such queries.
I am trying to group rows in MySQL but end up with a wrong result.
My DB looks like this:
I'm using this query:
SELECT
r_id, va_id,va_klasse,va_periode,
1va_mer,1va_hjem,1va_mot,1va_bil,1va_fit,1va_hand,1va_med,1va_fra,
2va_mer,2va_hjem,2va_trae,2va_bil,2va_sty,2va_mus,2va_med,2va_fra,
3va_mer,3va_hjem,3va_mot,3va_bil,3va_pima,3va_nat,3va_med,3va_fra,
va_lock, va_update
FROM o6hxd_valgfag
WHERE va_klasse IN('7A','7B','7C','8A','8B','8C','9A','9B','9C')
GROUP BY va_id
ORDER BY va_klasse,va_name
This produces a wrong result, where one row is returned with only the first three numbers 123 and not the ones from row two and three.
What I would like is a result where the numbers 123, 321 and 132 are gathered in one line.
I can explain more detailed if this isn't sufficient.
If across those fields there should only be ever one value, you should really have them all in the same record and go about fixing it to insert and update the same record.
Ie I am aware that you database isn't designed correctly
However
To dig you out, you could give this a crack, I suppose.
SELECT
r_id, va_id,va_klasse,va_periode,
MAX(1va_mer),MAX(1va_hjem),MAX(1va_mot),MAX(1va_bil),MAX(1va_fit),MAX(1va_hand),MAX(1va_med),MAX(1va_fra),
MAX(2va_mer),MAX(2va_hjem),MAX(2va_trae),MAX(2va_bil),MAX(2va_sty),MAX(2va_mus),MAX(2va_med),MAX(2va_fra),
MAX(3va_mer),MAX(3va_hjem),MAX(3va_mot),MAX(3va_bil),MAX(3va_pima),MAX(3va_nat),MAX(3va_med),MAX(3va_fra),
va_lock, va_update
FROM o6hxd_valgfag
WHERE va_klasse IN('7A','7B','7C','8A','8B','8C','9A','9B','9C')
GROUP BY va_id
ORDER BY va_klasse,va_name
Your query will not work as intended. Think about this use-case:
what if for row1 (r_id =9), the fields 2va_sty, 2va_mus, 2va_med are not empty and has values?
In such case what should your desired output be? It certainly cannot be the numbers 123, 321 and 132 gathered in one line. Group by is usually used if you want to use aggregate functions executed against a certain field value, in your case va_id.
Not a solution to your problem but i think a better query would be like this (because of the not named columns in the group by clause https://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html):
SELECT
aa.r_id, aa.va_id, aa.va_klasse, aa.va_periode,
aa.1va_mer, aa.1va_hjem, aa.1va_mot, aa.1va_bil, aa.1va_fit, aa.1va_hand, aa.1va_med, aa.1va_fra,
aa.2va_mer, aa.2va_hjem, aa.2va_trae, aa.2va_bil, aa.2va_sty,2va_mus, aa.2va_med, aa.2va_fra,
aa.3va_mer, aa.3va_hjem, aa.3va_mot, aa.3va_bil, aa.3va_pima, aa.3va_nat, aa.3va_med, aa.3va_fra,
aa.va_lock, aa.va_update
FROM o6hxd_valgfag AS aa
INNER JOIN (
SELECT va_id
FROM o6hxd_valgfag
GROUP BY va_id
) AS _aa
ON aa.va_id = _aa.va_id
WHERE aa.va_klasse IN ('7A','7B','7C','8A','8B','8C','9A','9B','9C')
ORDER BY aa.va_klasse, aa.va_name;
Ive got a simple query that is used on a search. My problem is with this query is that as the records in mysql are added everytime there is a transaction, the query returns a list of data when there could only be one or a few more rows instead of a lot more.
SQLFliddle
As you can see here - the query returns a lot of rows, where I want it to return
BLSH103 A001A 31 24/01/2014
Can the qty where the product name & pallet space are the same be summed? And then show the largest date?
just use a sum function on t.Quantity (and a group by clause)
SELECT (t.ProductName) as Pname ,(s.PalletSpace) as PSpace, sum(t.Quantity) as Qty,(t.TransactionDate) as Transac
FROM PalletSpaces s
JOIN ProductTrans t
ON s.PalletSpaceID = t.PalletSpace
WHERE t.ProductName LIKE 'BLSH103' OR s.PalletSpace LIKE 'BLSH103'
group by
Pname,
pSpace,
Transac -- if you want to group by date also...
By the way, using LIKE this way (without %) doesn't make much sense...
see SqlFiddle
You just need to use GROUP BY and SUM in this way:
SELECT (t.ProductName) as Pname ,(s.PalletSpace) as PSpace, SUM(t.Quantity) as Qty,(t.TransactionDate) as Transac
FROM PalletSpaces s
JOIN ProductTrans t
ON s.PalletSpaceID = t.PalletSpace
WHERE t.ProductName LIKE 'BLSH103' OR s.PalletSpace LIKE 'BLSH103'
GROUP BY t.ProductName, s.PalletSpace;
I have the following query:
SELECT routes.route_date, time_slots.name, time_slots.openings, time_slots.appointments
FROM routes
INNER JOIN time_slots ON routes.route_id = time_slots.route_id
WHERE route_date
BETWEEN 20140109
AND 20140115
AND time_slots.openings > time_slots.appointments
ORDER BY route_date, name
This works just fine and will produce the following results:
What I want to do is only return one name per date. So the 9th, name = 1, would only have 1 result, rather than 2, as it currently does.
UPDATE: See the SQLFIDDLE for different type of solutions here: http://sqlfiddle.com/#!2/9ac65b/6
Will it solve your request if you use...
SELECT DISTINCT routes.route_date...your query... ?
It depends if you know that your rows always will have the same values, for same date/name.
Otherwise use group by...
(which I think suits your request best)
SELECT routes.route_date, time_slots.name, sum(time_slots.openings), sum(time_slots.appointments)
FROM routes
INNER JOIN time_slots ON routes.route_id = time_slots.route_id
WHERE route_date
BETWEEN 20140109
AND 20140115
AND time_slots.openings > time_slots.appointments
group by routes.route_date, time_slots.name
ORDER BY route_date, name
(i did a sum for the openings and appointments, you could do min, max, count, etc. Pick the one that fits your requirements best!)
You need to figure out which "name" you want when there are several for the same date.
Then you can group by date and select the right "name" by using an aggregate function like COUNT, MAX, etc.
I can't help you more if you don't explain your rule for picking one.
I am trying to determine the count of attendance for a training course between 2007-2013. I need it to pull the employees job group they were in during the time frame:
SELECT O867IA_VJOBHST.JOB_CLS_CD, O867IA_VJOBHST.DIS_NR,
Sum(IIf(emp_tng_stt_dt Between #1/1/2007# And #12/31/2011#,1,0)) AS [2007-2011],
Sum(IIf(emp_tng_stt_dt Between #1/1/2011# And #12/31/2011#,1,0)) AS 2011,
Sum(IIf(emp_tng_stt_dt Between #1/1/2012# And #12/31/2012#,1,0)) AS 2012,
Sum(IIf(emp_tng_stt_dt Between #1/1/2013# And #9/23/2013#,1,0)) AS 2013, O867IA_VJOBHST.REC_EFF_STT_DT, O867IA_VTRAING.EMP_TNG_STT_DT
FROM (O867IA_VJOBHST INNER JOIN O867IA_VTRAING ON O867IA_VJOBHST.SYS_EMP_ID_NR = O867IA_VTRAING.SYS_EMP_ID_NR) INNER JOIN O867IA_VPJOBCO ON O867IA_VJOBHST.JOB_CLS_CD = O867IA_VPJOBCO.JOB_CLS_CD
WHERE (((O867IA_VTRAING.REG_NR)="03") AND ((O867IA_VTRAING.TNG_SYS_NR)="0918") AND ((O867IA_VPJOBCO.JOB_GRP_CD)="61"))
GROUP BY O867IA_VJOBHST.JOB_CLS_CD, O867IA_VJOBHST.DIS_NR, O867IA_VJOBHST.REC_EFF_STT_DT, O867IA_VTRAING.EMP_TNG_STT_DT;
The REC_EFF_STT_DT field is the date they were recorded in their job, so I am trying to get that to be the MAX date, and it needs to be less than EMP_TNG_STT_DT which is when the training course was held. I try set it up like (((O867IA_VJOBHST.REC_EFF_STT_DT)<[O867IA_VTRAING].[EMP_TNG_STT_DT])); but it keeps giving me an error "you tried to execute a query that does not include the specified expression" whenever I add the MAX to REC EFF STT DT. I cannot find any solutions and need assistance.
If your ((MAX(O867IA_VJOBHST.REC_EFF_STT_DT) < [O867IA_VTRAING].[EMP_TNG_STT_DT])) is giving you this error, then perhaps it is also in your SELECT list, and is not just a 'Whereclause. Try removing it from yourSELECT` list.
Another suggestion is that [O867IA_VTRAING].[EMP_TNG_STT_DT] is not aggregated. You may be able to get this to work by aggregating that too. If you want the unaltered value, a FIRST() may work.