我想对SQL请求中的前几行进行一些数学运算,以避免在我的代码中执行此操作。
我有一个表格,代表两个实体的销售额(这里所代表的数据没有多大意义,只是一个摘录):
YEAR ID SALES PURCHASE MARGIN
2009 1 10796820,57 2662369,19 8134451,38
2009 2 2472271,53 2066312,34 405959,19
2008 1 9641213,19 1223606,68 8417606,51
2008 2 3436363,86 2730035,19 706328,67
我想知道销售,购买,保证金......是如何发展的,并将其与前一年进行比较。
简而言之,我想要一个预先计算好的演变的SQL结果:
YEAR ID SALES SALES_EVOLUTION PURCHASE PURCHASE_EVOLUTION MARGIN MARGIN_EVOLUTION
2009 1 10796820,57 11,99 2662369,19 117,58 8134451,38 -3,36
2009 2 2472271,53 -28,06 2066312,34 -24,31 405959,19 -42,53
2008 1 9641213,19 1223606,68 8417606,51
2008 2 3436363,86 2730035,19 706328,67
我可以做一些丑陋的事情:
SELECT *, YEAR, ID, SALES , (SALES/(SELECT SALES FROM TABLE WHERE YEAR = OUTER_TABLE.YEAR-1 AND ID = OUTER_TABLE.ID) -1)*100 as SALES_EVOLUTION (...)
FROM TABLE as OUTER_TABLE
ORDER BY YEAR DESC, ID ASC
但我有20个字段,我必须做一个嵌套查询,这意味着我会有一个非常庞大和丑陋的查询。
有没有更好的方法来做这个,少用SQL?
答案 0 :(得分:2)
旧skool解决方案:
SELECT c.YEAR, c.ID, c.SALES, c.PURCHASE, c.MARGIN
, p.YEAR, p.ID, p.SALES, p.PURCHASE, p.MARGIN
FROM tab AS c -- current
INNER JOIN tab AS p -- previous
ON c.year = p.year - 1
AND c.id = p.id
如果您有一个具有分析功能的数据库(MS SQL,Oracle),您可以使用LEAD或LAG分析函数,请参阅http://www.oracle-base.com/articles/misc/LagLeadAnalyticFunctions.php
我认为这是正确的应用程序:
SELECT c.YEAR, c.ID, c.SALES, c.PURCHASE, c.MARGIN
, LAG(c.YEAR, 1, 0) OVER (ORDER BY ID,YEAR)
, LAG(c.ID, 1, 0) OVER (ORDER BY ID,YEAR)
, LAG(c.SALES, 1, 0) OVER (ORDER BY ID,YEAR)
, LAG(c.PURCHASE, 1, 0) OVER (ORDER BY ID,YEAR)
, LAG(c.MARGIN, 1, 0) OVER (ORDER BY ID,YEAR)
FROM tab AS c -- current
(不太确定,还没玩过这么多)
答案 1 :(得分:2)
使用sql server(但这应该适用于几乎所有的sql),提供的表可以使用 LEFT JOIN
DECLARE @Table TABLE(
[YEAR] INT,
ID INT,
SALES FLOAT,
PURCHASE FLOAT,
MARGIN FLOAT
)
INSERT INTO @Table ([YEAR],ID,SALES,PURCHASE,MARGIN) SELECT 2009,1,10796820.57,2662369.19,8134451.38
INSERT INTO @Table ([YEAR],ID,SALES,PURCHASE,MARGIN) SELECT 2009,2,2472271.53,2066312.34,405959.19
INSERT INTO @Table ([YEAR],ID,SALES,PURCHASE,MARGIN) SELECT 2008,1,9641213.19,1223606.68,8417606.51
INSERT INTO @Table ([YEAR],ID,SALES,PURCHASE,MARGIN) SELECT 2008,2,3436363.86,2730035.19,706328.67
SELECT cur.*,
((cur.Sales / prev.SALES) - 1) * 100
FROM @Table cur LEFT JOIN
@Table prev ON cur.ID = prev.ID AND cur.[YEAR] - 1 = prev.[YEAR]
LEFT JOIN 将允许您仍然看到2008年的值,其中 INNER JOIN 不会。
答案 2 :(得分:1)
你可以这样做:
SELECT t1.*, t1.YEAR, t1.ID, t1.SALES , ((t1.sales/t2.sales) -1) * 100 as SALES_EVOLUTION
(...)
FROM Table t1 JOIN Table t2 ON t1.Year = (t2.Year + 1) AND t1.Id = t2.Id
ORDER BY t1.YEAR DESC, t1.ID ASC
现在,如果你想比较更多年份,你必须做更多的连接,所以这是一个稍微丑陋的解决方案。