在SQL中获取聚合数据

时间:2015-02-06 03:54:32

标签: sql-server tsql

我有一个StatementsEntries表,如下所示

ID  |   Name       |  CaseId | StatementID  | Amount  |  Balance   | Paid
--------------------------------------------------------------------------
 1  |  Statement 1 |    1     |      1       |   1000  |  1000      |   1
--------------------------------------------------------------------------
 2  |  Payment     |    1     |      0       |   1000  |    0       |   0
--------------------------------------------------------------------------
 3  |  Statement 2 |    3     |      2       |    500  |    500     |   0
--------------------------------------------------------------------------
 4  |  Statement 3 |    4     |      3       |    50   |    50      |   0
--------------------------------------------------------------------------
 5  |  Payment     |    3     |      0       |    25   |    475     |   0

这是一个包含数百条记录的现有表格,基本上当有一个名称声明*和一个StatementId时,它意味着它被“开票”处理,那么对同一个案例ID的任何付款总是转到旧发票。在这种情况下,报表1已全额支付,因为该报表已生成,然后收到了余额金额的付款。

在声明2的情况下,它生成并且在声明3生成后收到付款,付款为25美元,因此付款适用于具有相同caseId的声明2,仅对特定情况ID付款被分配,所以如果我为CaseId 4付款,我会将其应用于对帐单3。

我想获得一个包含以下结果的查询:

 StatementId  |  Name        | Amount | Balance | IsPaid
----------------------------------------------------------
      1       |  Statement 1 |  1000  | 1000    |   1
---------------------------------------------------------
      1       |  Statement 1 |  1000  |   0     |   0
----------------------------------------------------------
      2       |  Statement 2 |  500   |  500    |   0
----------------------------------------------------------
      2       |  Statement 2 |   25   |  475    |   0
----------------------------------------------------------
      3       |  Statement 3 |   50   |  50     |   0

我已尝试使用UNION ALL,并加入同一个表但我正在努力为已付款的记录设置StatementId。会为此感到欣赏。

更新 我尝试了以下脚本

SELECT
    [Statement ID] = CASE WHEN s.StatementId> 0 THEN s.StatementId ELSE x.StatementId END,
    Name = CASE WHEN s.StatementId> 0 THEN s.Description ELSE x.Description END,
    s.Amount,
    s.Balance,
    s.IsPaid
FROM StatementEntries s
OUTER APPLY(
    SELECT *
    FROM StatementEntries
    WHERE
        CaseId = s.CaseId
        AND StatementId > s.StatementId AND StatementId > 0
    ORDER BY ID
)x
WHERE s.CaseId = 1
ORDER BY s.ID

产生

 StatementId  |  Name        | Amount | Balance | IsPaid
----------------------------------------------------------
      1       |  Statement 1 |  1000  | 1000    |   1
---------------------------------------------------------
      1       |  Statement 1 |  1000  |   0     |   0
----------------------------------------------------------
      2       |  Statement 2 |  500   |  500    |   0
----------------------------------------------------------
      1       |  Statement 1 |   25   |  475    |   0
----------------------------------------------------------
      3       |  Statement 3 |   50   |  50     |   0

请参阅记录#4,它应该显示语句ID 2和语句2.我正在尝试使其工作,非常感谢你的答案,虽然我认为它让我走上了正确的道路。

更新2(添加架构和示例数据)

CREATE TABLE StatementsEntries (
    Id              INT,
    Name            VARCHAR(200),
    Date            DATE,
    IsCredit        BIT,
    Amount          DECIMAL,
    CaseId          INT,
    IsAdjustment    BIT,
    StatementId     INT,
    Balance         DECIMAL,
    IsPaid          BIT,
    CreateDate      DATE
)

INSERT INTO StatementsEntries  VALUES
(1, 'Statement 4444','04/01/2007',0, 850,1,0,4444,850,1,'04/01/2007'),
(2, 'Payment made', '04/02/2007', 1, 850,1,0,0,0,0,'04/02/2007'),
(3, 'Statement 5555','08/01/2008', 0,1003, 1,0,5555,1003, 0,'08/01/2008'),
(4, 'Statement 7777','09/01/2008',0, 3000,2,0,7777,3000,0,'09/01/2008'),
(5, 'Statement 8883','10/01/2008', 0,1500, 5,0,8883,1500, 1,'10/01/2008'),
(6, 'Payment made', '10/02/2008', 1, 1500,5,0,0,0,0,'10/02/2008'),
(7, 'Statement 9992','11/01/2008',0, 1750,7,0,9992,1750,0,'11/01/2008'),
(8, 'Payment made', '04/02/2009', 1, 1002,1,0,0,648,0,'04/02/2009'),
(9, 'Statement 9994','08/01/2010', 0,1650, 1,0,9994,1650, 1,'08/01/2010'),
(10, 'Payment made', '09/02/2011', 1, 10,1,0,0,638,0,'09/02/2011');

5 个答案:

答案 0 :(得分:2)

示例数据:

Id          Name            Date       IsCredit Amount      CaseId      IsAdjustment StatementId Balance     IsPaid CreateDate
----------- --------------- ---------- -------- ----------- ----------- ------------ ----------- ----------- ------ ----------
1           Statement 4444  2007-04-01 0        850         1           0            4444        850         1      2007-04-01
2           Payment made    2007-04-02 1        850         1           0            0           0           0      2007-04-02
3           Statement 5555  2008-08-01 0        1003        1           0            5555        1003        0      2008-08-01
4           Statement 7777  2008-09-01 0        3000        2           0            7777        3000        0      2008-09-01
5           Statement 8883  2008-10-01 0        1500        5           0            8883        1500        1      2008-10-01
6           Payment made    2008-10-02 1        1500        5           0            0           0           0      2008-10-02
7           Statement 9992  2008-11-01 0        1750        7           0            9992        1750        0      2008-11-01
8           Payment made    2009-04-02 1        1002        1           0            0           648         0      2009-04-02
9           Statement 9994  2010-08-01 0        1650        1           0            9994        1650        1      2010-08-01
10          Payment made    2011-09-02 1        10          1           0            0           638         0      2011-09-02

<强>解

SELECT
    s.id,
    [Statement ID] = CASE WHEN s.StatementID > 0 THEN s.StatementID ELSE x.StatementID END,
    Name = CASE WHEN s.StatementID > 0 THEN s.Name ELSE x.Name END,
    s.Amount,
    s.Balance,
    s.IsPaid
FROM StatementsEntries s
OUTER APPLY(
    SELECT TOP 1 *
    FROM StatementsEntries
    WHERE
        CaseID = s.CaseID
        AND StatementID > 0
        AND ID < s.Id
    ORDER BY ID Desc
)x
ORDER BY [Statement ID], s.Id

<强> RESULT

id          Statement ID Name            Amount      Balance     IsPaid
----------- ------------ --------------- ----------- ----------- ------
1           4444         Statement 4444  850         850         1
2           4444         Statement 4444  850         0           0
3           5555         Statement 5555  1003        1003        0
8           5555         Statement 5555  1002        648         0
4           7777         Statement 7777  3000        3000        0
5           8883         Statement 8883  1500        1500        1
6           8883         Statement 8883  1500        0           0
7           9992         Statement 9992  1750        1750        0
9           9994         Statement 9994  1650        1650        1
10          9994         Statement 9994  10          638         0

答案 1 :(得分:1)

使用Cross Apply

SELECT Dense_rank()OVER(ORDER BY cs.name) StatementID,
       cs.name,
       amount,
       Balance,
       paid
FROM   Yourtable a
       CROSS apply (SELECT TOP 1 name
                    FROM   Yourtable  b
                    WHERE  a.CaseId = b.CaseId
                    ORDER  BY id) cs 

SqlFiddle Demo

答案 2 :(得分:1)

试试这个:

select distinct src.caseid, 
src.name, 
max(src.statementid) over (partition by src.caseid order by src.id)   statementid, 
src.amount, 
src.balance, 
src.paid ispaid
from tbl src
left join tbl tgt on tgt.caseid = src.caseid and tgt.statementid = 0
order by caseid, src.balance desc

Demo

注意:这不适用于SQL Server 2005下的SQL Server版本。

答案 3 :(得分:0)

使用示例数据,以下查询:

SELECT S.Id, S.Name, S.Date, S.IsCredit, S.Amount, S.CaseId, S.IsAdjustment, S.StatementId, S.Balance, S.IsPaid, S.CreateDate
FROM 
    StatementsEntries S
WHERE
   S.IsCredit = 0

UNION ALL

SELECT P.Id, S.Name, P.Date, P.IsCredit, P.Amount, P.CaseId, P.IsAdjustment, S.StatementId, P.Balance, P.IsPaid, P.CreateDate
FROM 
    StatementsEntries P
    CROSS APPLY (
        SELECT TOP (1)  S.StatementId, S.Name
        FROM StatementsEntries S
        WHERE
            S.CaseId = P.CaseId
            AND S.IsCredit = 0
            AND S.Id < P.Id
        ORDER 
            BY S.Id DESC
    ) S
WHERE
    IsCredit = 1

ORDER BY StatementId, Id

产生以下结果:

╔════╦════════════════╦════════════╦══════════╦════════╦════════╦══════════════╦═════════════╦═════════╦════════╦════════════╗
║ Id ║      Name      ║    Date    ║ IsCredit ║ Amount ║ CaseId ║ IsAdjustment ║ StatementId ║ Balance ║ IsPaid ║ CreateDate ║
╠════╬════════════════╬════════════╬══════════╬════════╬════════╬══════════════╬═════════════╬═════════╬════════╬════════════╣
║  1 ║ Statement 4444 ║ 2007-04-01 ║        0 ║    850 ║      1 ║            0 ║        4444 ║     850 ║      1 ║ 2007-04-01 ║
║  2 ║ Statement 4444 ║ 2007-04-02 ║        1 ║    850 ║      1 ║            0 ║        4444 ║       0 ║      0 ║ 2007-04-02 ║
║  3 ║ Statement 5555 ║ 2008-08-01 ║        0 ║   1003 ║      1 ║            0 ║        5555 ║    1003 ║      0 ║ 2008-08-01 ║
║  8 ║ Statement 5555 ║ 2009-04-02 ║        1 ║   1002 ║      1 ║            0 ║        5555 ║     648 ║      0 ║ 2009-04-02 ║
║  4 ║ Statement 7777 ║ 2008-09-01 ║        0 ║   3000 ║      2 ║            0 ║        7777 ║    3000 ║      0 ║ 2008-09-01 ║
║  5 ║ Statement 8883 ║ 2008-10-01 ║        0 ║   1500 ║      5 ║            0 ║        8883 ║    1500 ║      1 ║ 2008-10-01 ║
║  6 ║ Statement 8883 ║ 2008-10-02 ║        1 ║   1500 ║      5 ║            0 ║        8883 ║       0 ║      0 ║ 2008-10-02 ║
║  7 ║ Statement 9992 ║ 2008-11-01 ║        0 ║   1750 ║      7 ║            0 ║        9992 ║    1750 ║      0 ║ 2008-11-01 ║
║  9 ║ Statement 9994 ║ 2010-08-01 ║        0 ║   1650 ║      1 ║            0 ║        9994 ║    1650 ║      1 ║ 2010-08-01 ║
║ 10 ║ Statement 9994 ║ 2011-09-02 ║        1 ║     10 ║      1 ║            0 ║        9994 ║     638 ║      0 ║ 2011-09-02 ║
╚════╩════════════════╩════════════╩══════════╩════════╩════════╩══════════════╩═════════════╩═════════╩════════╩════════════╝

答案 4 :(得分:0)

这应该可以解决问题

SELECT id,
      ISNULL([Statement].StatementId, SE.StatementId) AS StatementId
    , ISNULL([Statement].Name, SE.Name) AS Name
    , Date         
    , IsCredit     
    , Amount       
    , CaseId       
    , IsAdjustment 
    , Balance      
    , IsPaid       
    , CreateDate   
FROM StatementsEntries AS SE
    OUTER APPLY(
        SELECT Name, StatementId
        FROM StatementsEntries AS SE_name
        WHERE SE_name.Id = SE.CaseId
            AND SE.IsCredit = 1
    ) AS [Statement]
ORDER BY StatementId