简体   繁体   English

将表中的数据合并到一行T-SQL

[英]Combine data from a table to one row T-SQL

I have a table in #SQL server 2008 that has transaction data. 我在#SQL server 2008中有一个包含事务数据的表。 The table looks like this. 该表看起来像这样。 I would like to have this in a sql statement. 我想在sql语句中有这个。

TransactionId|TransactionDate|TransactionType|Amount|Balance|UserId TRANSACTIONID | TransactionDate | TRANSACTIONTYPE |金额|资产|用户ID

The transaction type can be one of four types, Deposit, Withdrawals, Profit and Stake. 交易类型可以是四种类型之一:存款,取款,利润和股权。 I give an example how it can look like in the transaction table. 我举一个例子说明它在事务表中的样子。 The balance is the Sum of amount column. 余额是金额总和列。

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

What I want now is to get a select statement that gives me all data grouped by week. 我现在想要的是获得一个select语句,它为我提供按周分组的所有数据。 The result should look like this. 结果应该是这样的。

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

I have also problem with the weeks... I live in Europe an my first day in a week is monday. 我也有几周的问题......我住在欧洲一个星期的第一天是星期一。 I have a solution for that but around the end of a year I get sometimes week 54 but there are only 52 weeks in a year... 我有一个解决方案,但在一年结束时,我有时会得到54周,但一年只有52周......

I hope someone can help me out. 我希望有人可以帮助我。

This is what I have so far. 这就是我到目前为止所拥有的。

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 

Here's sample data and my query on sql-fiddle: http://www.sqlfiddle.com/#!3/79d65/92/0 这里的示例数据和我对sql-fiddle的查询: http ://www.sqlfiddle.com/#!3/79d65 / 92/0

In order to transform the data from the rows into columns, you will want to use the PIVOT function. 为了将行中的数据转换为列,您将需要使用PIVOT函数。

You did not specify what balance value you want to return but based on the final result, it looks like you want the final balance to be the value associated with the last transaction date for each day. 您没有指定要返回的balance值,但根据最终结果,您希望最终余额为与每天的最后交易日期相关联的值。 If that is not correct, then please clarify what the logic should be. 如果这不正确,那么请说明逻辑应该是什么。

In order to get the result you will want to use the DATEPART and YEAR functions. 为了获得结果,您将需要使用DATEPARTYEAR函数。 These will allow grouping by both the week and year values. 这些将允许按周和年值进行分组。

The following query should get the result that you want: 以下查询应该获得您想要的结果:

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;

See SQL Fiddle with Demo . 请参阅SQL Fiddle with Demo The result is: 结果是:

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

As a side note, you stated that your start of the week is Monday, you might have to use the DATEFIRST function to set the first day of the week. 作为附注,你说你的星期一是星期一,你可能必须使用DATEFIRST函数来设置一周的第一天。

Another option, without using PIVOT, but rather with few CASEs 另一种选择,不使用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 Demo SQLFiddle演示

http://www.sqlfiddle.com/#!3/79d65/89 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM