3

我在#SQL server 2008 中有一个包含事务数据的表。桌子看起来像这样。我想在 sql 语句中有这个。

TransactionId|TransactionDate|TransactionType|Amount|Balance|UserId

交易类型可以是存款、取款、利润和权益四种类型之一。我举一个例子,它在事务表中的样子。余额是金额总和列。

TransactionId|TransactionDate|TransactionType|Amount|Balance|UserId
1|             2013-03-25|      Deposit|         150|    150|     1
2|             2013-03-27|      Stake|           -20|    130|     1
3|             2013-03-28|      Profit |         1500|   1630|    1
4 |            2013-03-29|      Withdrawals|     -700|   930|     1
5|             2013-03-29|      Stake |          -230 |  700 |    1
6|             2013-04-04|      Stake|           -150 |  550|     1
7|             2013-04-06|      Stake |          -150 |  400|     1

我现在想要的是获得一个选择语句,它为我提供按周分组的所有数据。结果应该是这样的。

Week|Deposit|Withdrawals|Stake|Profit|Balance|Year
13 |  150|     -700  |      -250 | 1500 |  700 |    2013
14 |  0  |     0     |      -300|  0   |   400 |    2013

我也有几周的问题......我住在欧洲,一周的第一天是星期一。我有一个解决方案,但在一年结束时我有时会得到第 54 周,但一年中只有 52 周......

我希望有人可以帮助我。

这就是我到目前为止所拥有的。

SELECT transactionid, 
       transactiondate, 
       transactiontype, 
       amount, 
       (SELECT Sum(amount) 
        FROM   transactions AS trans_ 
        WHERE  trans_.transactiondate <= trans.transactiondate 
               AND userid = 1)         AS Balance, 
       userid, 
       Datepart(week, transactiondate) AS Week, 
       Datepart(year, transactiondate) AS Year 
FROM   transactions trans 
WHERE  userid = 1 
ORDER  BY transactiondate DESC, 
          transactionid DESC 

这是示例数据和我对 sql-fiddle 的查询:http ://www.sqlfiddle.com/#!3/79d65/92/0

4

3 回答 3

1

为了将数据从行转换为列,您需要使用PIVOT函数。

您没有指定balance要返回的值,但根据最终结果,您似乎希望最终余额是与每一天的最后交易日期关联的值。如果这不正确,那么请澄清逻辑应该是什么。

为了获得结果,您需要使用DATEPARTYEAR函数。这些将允许按周和年值进行分组。

以下查询应该得到您想要的结果:

select week, 
  coalesce(Deposit, 0) Deposit, 
  coalesce(Withdrawals, 0) Withdrawals, 
  coalesce(Stake, 0) Stake, 
  coalesce(Profit, 0) Profit,
  Balance,
  Year
from
(
  select datepart(week, t1.transactiondate) week,
    t1.transactiontype,
    t2.balance,
    t1.amount,
    year(t1.transactiondate) year
  from transactions t1
  cross apply
  (
    select top 1 balance 
    from transactions t2
    where datepart(week, t1.transactiondate) = datepart(week,  t2.transactiondate)
      and year(t1.transactiondate) = year(t2.transactiondate)
      and t1.userid = t2.userid
    order by TransactionId desc
  ) t2
) d
pivot
(
  sum(amount)
  for transactiontype in (Deposit, Withdrawals, Stake, Profit)
) piv;

请参阅SQL Fiddle with Demo。结果是:

| WEEK | DEPOSIT | WITHDRAWALS | STAKE | PROFIT | BALANCE | YEAR |
------------------------------------------------------------------
|   13 |     150 |        -700 |  -250 |   1500 |     700 | 2013 |
|   14 |       0 |           0 |  -300 |      0 |     400 | 2013 |

作为旁注,您声明一周的开始是星期一,您可能必须使用DATEFIRST函数来设置一周的第一天。

于 2013-03-30T14:43:27.327 回答
1

另一种选择,不使用 PIVOT,而是使用很少的 CASE

WITH CTE AS
(
    SELECT
         TransactionId 
        ,TransactionDate
        ,DATEPART(WEEK, TransactionDate) AS Week
        ,CASE WHEN TransactionType='Deposit' THEN Amount ELSE 0 END AS Deposit 
        ,CASE WHEN TransactionType='Stake' THEN Amount ELSE 0 END AS Stake 
        ,CASE WHEN TransactionType='Profit' THEN Amount ELSE 0 END AS Profit 
        ,CASE WHEN TransactionType='Withdrawals' THEN Amount ELSE 0 END AS Withdrawals 
        ,Balance
        ,DATEPART(YEAR, TransactionDate) AS Year
    FROM dbo.Transactions
)
SELECT 
  Week,  SUM(Deposit) AS Deposit, SUM(Withdrawals) AS Withdrawals, SUM(Stake) AS Stake, SUM(Profit) AS Profit, 
    (SELECT Balance FROM CTE i WHERE i.TransactionID = MAX(o.TransactionID)) AS BAlance, Year
FROM CTE o
GROUP BY Week, Year

SQLFiddle 演示

于 2013-03-30T14:56:18.040 回答
0

http://www.sqlfiddle.com/#!3/79d65/89

;WITH cte AS
(
  SELECT datepart(ww, transactiondate) wk,
  sum(CASE WHEN TransactionType = 'Deposit' THEN Amount ELSE 0 END) AS D,
  sum(CASE WHEN TransactionType = 'Withdrawals' THEN Amount ELSE 0 END)  AS W,
  sum(CASE WHEN TransactionType = 'Profit' THEN Amount ELSE 0 END) AS P,
  sum(CASE WHEN TransactionType = 'Stake' THEN Amount ELSE 0 END)  AS S,
  sum(
    CASE WHEN TransactionType = 'Deposit' THEN Amount ELSE 0 END +
    CASE WHEN TransactionType = 'Withdrawals' THEN Amount ELSE 0 END +
    CASE WHEN TransactionType = 'Profit' THEN Amount ELSE 0 END +
    CASE WHEN TransactionType = 'Stake' THEN Amount ELSE 0 END +
    CASE WHEN TransactionType = 'Balance' THEN Amount ELSE 0 END) AS wkTotal
  FROM transactions
  GROUP BY datepart(ww, transactiondate)),
  cte1 AS
  (
    SELECT *, row_number() over (ORDER BY wk) AS rowNum
    FROM cte)
  SELECT wk, d, w, p, s, wktotal
  + coalesce((SELECT top 1 wktotal FROM cte1 x WHERE x.rownum < m.rownum ), 0) AS RunningBalance
FROM cte1 m
于 2013-03-30T14:55:10.733 回答