查询过滤掉具有确切偏移量

时间:2017-10-26 17:59:28

标签: sql sql-server filter sum offset

下面的查询是一个草稿,其中包含我要编写的查询中的相关列,因此不要将其视为解决方案。将其用作表和列名称的指南。我正在尝试删除相同的ORDER_ID和ACCOUNT_ID相互抵消的任何事务。我不认为我可以使用SUM进行聚合,因为这会将所有TX_AMOUNT值加在一起进行分组。请参见TX_ID 6和7.这些都需要在结果集中显示。如何输出下表中的TX_ID,并滤除任何不说“显示”的东西?

SELECT 
T1.ACCOUNT_ID
T1.ORDER_ID,
T1.TX_ID
FROM TRANSACTION AS T1
WHERE
T1.ACCOUNT_ID IN (
SELECT T2.ACCOUNT_ID
FROM TRANSACTION AS T2
GROUP BY T2.ACCOUNT_ID, T2.ORDER_ID
HAVING SUM(T2.TX_AMOUNT) != 0 AND T2.ORDER_ID IS NOT NULL 
)
AND T1.ORDER_ID IN (
SELECT T3.ORDER_ID
FROM TRANSACTION AS T3
GROUP BY T3.ACCOUNT_ID, T3.ORDER_ID
HAVING SUM(T3.TX_AMOUNT) != 0 AND T3.ORDER_ID IS NOT NULL 
)

TX_ID   ORDER_ID ACCOUNT_ID  TX_AMOUNT
------------------------------------
1       A1       200         -3.00  <--------- DON'T SHOW THIS; OFFSET BY #2
2       A1       200         3.00   <--------- DON'T SHOW THIS; OFFSET BY #1
3       A1       200         3.00   <--------- SHOW THIS
4       A2       999         -10.01 <--------- DON'T SHOW THIS; OFFSET BY #5
5       A2       999         10.01  <--------- DON'T SHOW THIS; OFFSET BY #4
6       A2       999         10.01  <--------- SHOW THIS
7       A2       999         5.02   <--------- SHOW THIS

1 个答案:

答案 0 :(得分:2)

版本2: MUCH 更清洁...... Working DEMO with comments(您可能需要点击运行它!)才能看到所需的结果(或者我有一个缓存问题)

  • CTE(通用表格表达式)只是您显示的数据设置
  • CTE2只是添加一个由tx_amount,order_Id,account_Id分区的行号。这里的关键是我们得到每个order_ID的row_number,Account_ID和tax_Amount在这3个值改变时重新启动,但在它们保持不变时递增。这后来允许我们在相反的tx_amounts上排除相似的匹配而不消除那些当一方有多于另一方时(你的$ 3.00例子)
  • Select只是从基集中提取记录,其中存在具有相同行号order_id和帐户的相反值。如果没有,那么我们就知道这是一个没有匹配tx_Amount的值,因此我们想保留它。
  • 询问您是否有疑问!如果有什么不清楚的话,很乐意提供帮助
  • 最后,如果我们改变CTE2,那么rowNumber()按tx_ID asc而不是tx_Amount desc排序(除了我需要在row_nubmer上订单之外没有任何其他目的),那么我们就会在FIFO方法之后首先一致地摆脱最低数量的匹配)

With CTE (TX_ID,   ORDER_ID, ACCOUNT_ID,  TX_AMOUNT) as (

SELECT 1,       'A1',       200,         -3.00  UNION ALL
SELECT 2,       'A1',       200,         3.00   UNION ALL
SELECT 3,       'A1',       200,         3.00   UNION ALL
SELECT 4,       'A2',       999,         -10.01 UNION ALL
SELECT 5,       'A2',       999,         10.01  UNION ALL
SELECT 6,       'A2',       999,         10.01  UNION ALL
SELECT 7,       'A2',       999,         5.02 ),

cte2 as (
SELECT A.*, row_number() over (partition by order_ID, Account_ID, Tx_Amount order by tx_Amount desc) RN
FROM cte A)

SELECT * 
FROM cte2 A
WHERE NOT exists (SELECT * 
                  FROM cte2 B
                  WHERE A.Order_ID = B.Order_ID
                    and A.Account_ID = B.Account_Id
                    and A.tx_Amount*-1 = B.tx_Amount
                    and A.RN = B.RN)

给我们:(注意我们应该通过将*更改为所需的字段来消除RN,但此时我太懒了)

+----+-------+----------+------------+-----------+----+
|    | TX_ID | ORDER_ID | ACCOUNT_ID | TX_AMOUNT | RN |
+----+-------+----------+------------+-----------+----+
|  1 |     2 | A1       |        200 |      3,00 |  2 |
|  2 |     7 | A2       |        999 |      5,02 |  1 |
|  3 |     5 | A2       |        999 |     10,01 |  2 |
+----+-------+----------+------------+-----------+----+

版本1 :(抓住这个丑陋的;我的意思是认真的;谁这么想?)我这样做......

  1. 做点什么。 (第1版)
  2. 笑(一个重要的,被忽视的一步)
  3. 然后做正确的(参见上面的第2版)
  4. 现在让它变得更好。 (索引,调整连接拼写,布局注释,在CTE2中的row_number逻辑上使用正确的顺序)
  5. DEMO

    With CTE (TX_ID,   ORDER_ID, ACCOUNT_ID,  TX_AMOUNT) as (
    
    SELECT 1,       'A1',       200,         -3.00  UNION ALL
    SELECT 2,       'A1',       200,         3.00   UNION ALL
    SELECT 3,       'A1',       200,         3.00   UNION ALL
    SELECT 4,       'A2',       999,         -10.01 UNION ALL
    SELECT 5,       'A2',       999,         10.01  UNION ALL
    SELECT 6,       'A2',       999,         10.01  UNION ALL
    SELECT 7,       'A2',       999,         5.02 ),
    cte2 as (
    SELECT * 
    FROM (Select A.Tx_Id aTx_ID
               , A.order_ID as AOrderID
               , A.Account_ID as AAccount_ID
               , A.tx_Amount as ATx_Amount
               , Row_number() over (partition by Order_ID, Account_ID, tx_Amount order by tx_Amount asc) ARN
    
          from cte a 
          WHERE tx_Amount <=0) A
    FULL OUTER JOIN (SELECT b.tx_Id
                          , b.order_Id
                          , b.Account_Id
                          , b.tx_Amount
                          ,  Row_number() over (partition by Order_ID, Account_ID, tx_Amount order by tx_Amount desc) BRN 
                     FROM  CTE B 
                     WHERE  tx_Amount>0) B
      on A.AOrderID = B.Order_ID
     and A.AAccount_ID = B.Account_ID
     and A.ATx_Amount*-1 = B.tx_Amount
     and A.ARN=B.BRN
    Where a.Atx_ID is null
      or B.tx_ID is null)
    
      Select ATX_ID, AORDERID, AAccount_ID, ATX_AMOUNT from cte2 where ATX_ID is not null
      UNION ALL
      Select TX_ID, ORDER_ID, Account_ID, TX_AMOUNT from cte2 where TX_ID is not null