Математика с предыдущей строкой в ​​SQL, избегая вложенных запросов? - PullRequest
2 голосов
/ 08 января 2010

Я хочу выполнить некоторые математические операции с предыдущими строками в запросе 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?

Ответы [ 3 ]

2 голосов
/ 08 января 2010

Старый раствор для школы:

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 / article / 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

(не совсем уверен, не играл с этим достаточно)

2 голосов
/ 08 января 2010

Использование сервера sql (но это должно работать практически для любого 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 не будет .

1 голос
/ 08 января 2010

Вы можете сделать это так:

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

Теперь, если вы хотите сравнить больше лет, вам придется делать больше объединений, так что это немного уродливое решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...