从多行创建缺失或不匹配的数据查询

时间:2018-05-02 20:02:37

标签: sql sql-server

我已经搜索了高低,并且花了几天尝试不同的连接组合无济于事,所以欢迎集体建议。我创建了多个连接方案,并且"与#34;陈述,无法帮助我找不到明显的解决方案。

背景

作为示例,我们有一个表格,其列类似于: -

BuySideTradeDate | BuySideContract | BuySidePrice | BuySideQuantity | SellSideTradeDate | SellSideContract | SellSidePrice | SellSideQuantity

这是一个示例表,但概念是相同的。此表的目的是存储来自内部系统和外部系统的数据,以比较任何差异或任何缺失的数据。对于这个例子,我们假设每天执行一笔交易。每个交易问题都会有一个单独的行,例如: -

  1. 我们可能会在买方上完成交易 卖方(表格中只有一行用于此交易 只有购买信息完成)。

  2. 相反,我们可能会在卖方缺席 买方(表格中只有一行用于此交易 只有完成的销售信息)。

  3. 我们可能会在买入的卖方进行交易 方但价格可能不同(将有两行 已填充相应列的表格。

  4. 挑战

    我们需要创建一个查询来做两件事;首先是" matche"相同的合同(在买卖双方)和双方的交易日期(如果存在两个匹配的行),然后,如果没有匹配,我们需要简单地返回该单行(无论它是否'购买方或卖方已填充)。如果合同和交易日期匹配,我们需要将这两行合并为一个!

    基本上,这会为报告提供数据,用于发现任何一方的交易缺失或交易不匹配。

    示例输入数据(感谢您提示@Radim)(抱歉格式不佳)

    BuySideTradeDate    BuySideContract BuySidePrice    BuySideQuantity SellSideTradeDate   SellSideContract    SellSidePrice   SellSideQuantity
    
    10/04/2018  Sugar   100 10              
    15/04/2018  Sugar   101 12              
    16/04/2018  Coffee  200 10              
    20/04/2018  Corn    300 11              
    25/04/2018  Corn    305 15              
                                   10/04/2018   Sugar   100.5   10
                                   15/04/2018   Sugar   101     11
                                   16/04/2018   Coffee  201     10
                                   26/04/2018   Oil     1000    1
    
    Expected Output
    
    10/04/2018  Sugar   100 10  10/04/2018  Sugar   100.5   10 (contract/date/quantity match but price do not)
    15/04/2018  Sugar   101 12  15/04/2018  Sugar   101     11 (contract/date/price match but quantity does not)
    16/04/2018  Coffee  200 10  16/04/2018  Coffee  201     10 (contract/date/quantity match but price does not)
    20/04/2018  Corn    300 11 (missing from sell side)             
    25/04/2018  Corn    305 15 (missing from sell side)
                                26/04/2018  Oil     1000    1 (missing from buy side)
    

    我怀疑这是子查询和连接的组合,但有一种更简单的方法,我错过了!

    非常感谢任何意见!

    如果我太模糊或者你需要进一步明确,请大喊。

    感谢。

3 个答案:

答案 0 :(得分:0)

我创建了两个表:buy_sidesell_side

create table #buy_side (
    foo varchar(5) null
  , bar int null
  , san int null
);

create table #sell_side (
    foo varchar(5) null
  , bar int null
  , san int null
);

我为每个表添加值:

INSERT INTO #buy_side (foo, bar, san)
VALUES ('XYZ', 3, 5)
     , ('ABC', 11, 8)
     , ('XYP', 2, 5)

INSERT INTO #sell_side (foo, bar, san)
VALUES ('XYP', 8, 9)
     , ('ABC', 11, 8)
     , ('XYZ', 6, 4)

两个表之间只有一个值匹配:(' ABC',11,8)。

--In both buy and sell side
select * 
from #buy_side
INTERSECT
select * 
from #sell_side

--In buy side but not sell side
select * 
from #buy_side
EXCEPT
select * 
from #sell_side

--In sell side but not buy side
select * 
from #sell_side
EXCEPT
select * 
from #buy_side

以下是我运行这些结果时的结果......

this

只要两个表之间的模式(或关系,如果选择表的子集)匹配,这应该有效。

<强>更新

澄清最后的评论。我们假设您的所有数据都在同一个表格中。您将买卖与带旗帜的卖出区分开来;对于这个例子,我们说category。您可以选择购买记录。您可以选择销售记录。然后,您需要intersectexcept选择陈述。

create table #trade (
    foo varchar(5) null
  , bar int null
  , san int null
  , category varchar(max) null
);

INSERT INTO #trade (foo, bar, san, category)
VALUES ('XYZ', 3, 5, 'buy')
     , ('ABC', 11, 8, 'buy')
     , ('XYP', 2, 5, 'buy')
     , ('XYP', 8, 9, 'sell')
     , ('ABC', 11, 8, 'sell')
     , ('XYZ', 6, 4, 'sell')

SELECT foo, bar, san
FROM #trade
WHERE category = 'sell'
INTERSECT
SELECT foo, bar, san
FROM #trade
WHERE category = 'buy'

SELECT foo, bar, san
FROM #trade
WHERE category = 'sell'
EXCEPT
SELECT foo, bar, san
FROM #trade
WHERE category = 'buy'

SELECT foo, bar, san
FROM #trade
WHERE category = 'buy'
EXCEPT
SELECT foo, bar, san
FROM #trade
WHERE category = 'sell'

我在这里使用临时表因为它使创建示例变得更容易(我不必在之后进行清理)。你可以使用你喜欢的任何表格。

答案 1 :(得分:0)

首先将表连接到自身(使用两个不同的别名)。类似的东西:

SELECT BuySide.BuySidePrice,
  BuySide.BuySideQuantity,
  SellSide.SellSidePrice,
  SellSide.SellSideQuantity
FROM MyTable BuySide
  LEFT JOIN MyTable SellSide ON BuySide.BuySideTradeDate=SellSide.SellSideTradeDate AND BuySide.BuySideContract=SellSide.SellSideContract

到目前为止还没有完成,但这是让你到达目的地的第一步。我也不确定你是否想要匹配日期或合同;这个比较两者,但你可以很容易地修改它以匹配日期。

答案 2 :(得分:0)

您应该使用FULL JOIN。这允许在连接的任一侧保留NULL值,同时还组合&#34;匹配的&#34;的行。整个联接的价值。

示例:

SELECT BuySide.TradeDate, SellSide.TradeDate, etc...
FROM TBL_BuySide BuySide
FULL JOIN TBL_SellSide SellSide ON BuySide.TradeDate = SellSide.TradeDate
                                   AND BuySide.Contract = SellSide.Contract

作为一个说明,如果买卖双方中的两条线具有相同的交易日期和合约,则会产生重复。