我在#SQL server 2008中有一个包含交易数据的表。该表看起来像这样。我想在sql语句中有这个。
TRANSACTIONID | TransactionDate | TRANSACTIONTYPE |量|余额|用户ID
交易类型可以是四种类型之一:存款,取款,利润和股权。我举一个例子说明它在事务表中的样子。余额是金额列的总和。
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
我现在想要的是获取一个select语句,该语句为我提供按周分组的所有数据。结果应如下所示。
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
答案 0 :(得分:1)
为了将行中的数据转换为列,您需要使用PIVOT函数。
您没有指定要返回的balance
值,但根据最终结果,您希望最终余额为与每天的上一个交易日期相关联的值。如果这不正确,请澄清逻辑应该是什么。
为了获得结果,您需要使用DATEPART和YEAR函数。这些将允许按周和年值进行分组。
以下查询应该得到您想要的结果:
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功能来设置一周的第一天。
答案 1 :(得分: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
答案 2 :(得分: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