I have a table with the following structure:
doc_date date, doc_type varchar, code int primary key, qty int, price double
code ranges from 1 - 10; doc_type includes LP, FP, CAS, CRS;
I would like to query the table to get latest (Descending order of doc_date ) N number of records for each code where doc_type is either ' LP ' or ' FP ' and then average price .
I have been able to do everything I require apart from limiting the records for each code before the price is averaged.
My query is:
SELECT a.sfcode, a.productname, COALESCE((b.QTY - COALESCE(c.QTY,0)),0) AS currentstock, a.lastprice AS lprice, COALESCE(CAST(d.price AS decimal(16,3)),0) AS sprice, COALESCE(CAST(e.price AS decimal(16,3)),0) AS cprice FROM
(SELECT sfcode, productname, lastprice FROM products) AS a LEFT JOIN
(SELECT sfcode, SUM(COALESCE(QTY, 0)) AS QTY FROM transactions WHERE doctype IN ('FP','LP','CSR') GROUP BY sfcode) AS b ON a.sfcode = b.sfcode LEFT JOIN
(SELECT sfcode, SUM(QTY) AS QTY FROM transactions WHERE doctype IN ('FPR','LPR','CAS','CRS') GROUP BY sfcode) AS c ON a.sfcode = c.sfcode LEFT JOIN
(SELECT sfcode, AVG(unitprice) AS price FROM transactions WHERE doctype IN ('CAS', 'CRS') GROUP BY sfcode) AS d ON a.sfcode = d.sfcode LEFT JOIN
(SELECT sfcode, AVG(unitprice) AS price FROM transactions WHERE doctype IN ('FP', 'LP') GROUP BY sfcode) AS e ON a.sfcode = e.sfcode ORDER BY sfcode;
The last 2 lines of the query is where I need to limit the records in descending order of date before the price is averaged
I have searched for this and found http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/ where I am able to get limited rows but I don't know how to add the doc_type clause and get results based on desc date.
Link to sqlfiddle http://sqlfiddle.com/#!2/4778b/1
I want the result to look like this.. when the limit is set to 3:
| sfcode | stock | lprice | sprice | cprice |
| 1 | 40 | 15.000 | 0.000 | 9.667 |
| 2 | 80 | 25.000 | 0.000 | 19.667 |
| 3 | 120 | 35.000 | 0.000 | 29.66 |
| 4 | 160 | 45.000 | 0.000 | 39.667 |
| 5 | 200 | 55.000 | 0.000 | 49.667 |
| 6 | 0 | 65.000 | 0.000 | 0.000 |
| 7 | 0 | 75.000 | 0.000 | 0.000 |
| 8 | 0 | 85.000 | 0.000 | 0.000 |
| 9 | 0 | 95.000 | 0.000 | 0.000 |
| 10 | 0 |105.000 | 0.000 | 0.000 |
So based on the link that you provided, you can change your query to
set @row_limit = 3;
set @row_num = 0;
set @code = -1;
SELECT a.sfcode, COALESCE((b.QTY - COALESCE(c.QTY,0)),0) AS currentstock,
a.lastprice AS lprice, COALESCE(CAST(d.price AS decimal(16,3)),0) AS sprice,
COALESCE(CAST(e.price AS decimal(16,3)),0) AS cprice FROM
(SELECT sfcode, lastprice FROM products) AS a LEFT JOIN
(SELECT sfcode, SUM(COALESCE(QTY, 0)) AS QTY
FROM transactions
WHERE doctype IN ('FP','LP','CSR')
GROUP BY sfcode) AS b ON a.sfcode = b.sfcode LEFT JOIN
(SELECT sfcode, SUM(QTY) AS QTY
FROM transactions
WHERE doctype IN ('FPR','LPR','CAS','CRS')
GROUP BY sfcode) AS c ON a.sfcode = c.sfcode LEFT JOIN
(SELECT sfcode, AVG(unitprice) AS price
FROM (SELECT sfcode, unitprice,
@row_num := if(@code = sfcode, @row_num + 1, 0) AS rowNumber,
@code := sfcode AS code
FROM transactions
WHERE doctype IN ('CAS', 'CRS')
ORDER BY sfcode, docdate DESC) AS f
WHERE f.rowNumber < @row_limit GROUP BY sfcode)
AS d ON a.sfcode = d.sfcode
LEFT JOIN (SELECT sfcode, AVG(unitprice) AS price
FROM **(SELECT sfcode, unitprice,
@row_num := if(@code = sfcode, @row_num + 1, 0) as rowNumber,
@code := sfcode AS code
FROM transactions
WHERE doctype IN ('FP', 'LP')
ORDER BY sfcode, docdate DESC) AS g**
WHERE g.rowNumber < @row_limit GROUP BY sfcode)
AS e ON a.sfcode = e.sfcode ORDER BY sfcode;
where @row_limit
is set to the number of most recent transactions that you wish to collect.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.