修改我的SQL Server查询-有时返回太多行

时间:2018-08-14 22:45:33

标签: sql sql-server querying

我需要更新以下查询,以便每个父(声明)只返回一个子记录(汇款)。

表Remit_To_Activate的每项声明仅包含一个日期/时间戳,这正是我想要的。

但是,当我将整个汇款表加入其中时,由于某些索赔具有多个具有相同日期/时间戳的汇款,因此最外面的查询为每个索赔ID返回多于1行。

SELECT * FROM REMITTANCE 
WHERE BILLED_AMOUNT>0 AND ACTIVE=0 
AND REMITTANCE_UUID IN ( 
  SELECT REMITTANCE_UUID FROM Claims_Group2 G2
  INNER JOIN Remit_To_Activate t ON (
    (t.ClaimID = G2.CLAIM_ID) AND 
    (t.DATE_OF_LATEST_REGULAR_REMIT = G2.CREATE_DATETIME)
)
  where ACTIVE=0 and BILLED_AMOUNT>0
)

我相信,如果我在REmit_To_Activate中将REMITTANCE_UUID作为一列包含在内,则该问题将得到解决。那是真正的问题。这就是我创建Remit_To_Activate表的方式(试图获取索赔的最新汇款):

SELECT MAX(create_datetime) as DATE_OF_LATEST_REMIT,
MAX(claim_id) AS ClaimID,
INTO Latest_Remit_To_Activate 
FROM Claims_Group2
WHERE BILLED_AMOUNT>0
GROUP BY Claim_ID 
ORDER BY Claim_ID

Claims_Group2包含以下字段:   REMITTANCE_UUID,   CLAIM_ID,   BILLED_AMOUNT,   CREATE_DATETIME

这是当前给我带来问题的两行-它们都是SAME CLAIM和SAME TIMESTAMP的汇款。我只想在Remits_To_Activate表中使用其中之一,因此每个理赔只能“激活”一个汇款: enter image description here

3 个答案:

答案 0 :(得分:0)

您可以这样更改查询:

SELECT
  p.*, latest_remit.DATE_OF_LATEST_REMIT
FROM
  Remittance AS p inner join
(SELECT MAX(create_datetime) as DATE_OF_LATEST_REMIT,
claim_id,
FROM Claims_Group2
WHERE BILLED_AMOUNT>0
GROUP BY Claim_ID 
ORDER BY Claim_ID) as latest_remit
on latest_remit.claim_id = p.claim_id;

这只会给您一行。未经测试(因此请运行并进行更改)。

答案 1 :(得分:0)

如果没有有关数据库结构的更多信息,尤其是Claims_Group2REMITTANCE的结构以及它们之间的关系,就无法真正建议您如何进行汇款UUID放入DATE_OF_LATEST_REMIT

但是,由于您使用的是SQL Server,因此 可以使用window function引入一种综合手段,以便在具有相同时间戳的汇款中进行选择。例如,看起来您可以解决如下问题:

select *
from (
  select
    r.*,
    row_number() over (partition by cg2.claim_id order by cg2.create_datetime desc) as rn
  from
    remittance r
    join claims_group2 cg2
      on r.remittance_uuid = cg2.remittance_uuid
  where
    r.active = 0 
    and r.billed_amount > 0
    and cg2.active = 0
    and cg2.billed_amount > 0
  ) t
where t.rn = 1

请注意,它完全不依赖于DATE_OF_LATEST_REMIT表,因为它已包含在内联视图中。还请注意,这将在结果中引入额外的一列,尽管您可以通过枚举外部remittance子句中的表select的列来避免这种情况。

在两组activebilled_amount列上进行过滤似乎也很奇怪,但是这似乎跟从您在原始查询中所做的一样。因此,我敦促您仔细检查结果,因为将cg2列上的过滤条件提升到与remittance的连接级别会产生结果,该结果可能返回原始查询所做的行否(但每个claim_id不得超过一个)。

答案 2 :(得分:0)

一个同事向我提供了这种解决方案的优雅演示。我以前从未使用过“ over”或“ partition”。很棒!谢谢John和Gaurasvsa的投入。

if OBJECT_ID('tempdb..#t') is not null
drop table #t

select *, ROW_NUMBER() over (partition by CLAIM_ID order by CLAIM_ID) as ROW_NUM
into #t
from 
(
    select '2018-08-15 13:07:50.933' as CREATE_DATE, 1 as CLAIM_ID, NEWID() as 
    REMIT_UUID
    union select '2018-08-15 13:07:50.933', 1, NEWID()
    union select '2017-12-31 10:00:00.000', 2, NEWID()
) x 

select * 
from #t
order by CLAIM_ID, ROW_NUM

select CREATE_DATE, MAX(CLAIM_ID), MAX(REMIT_UUID)
from #t
where ROW_NUM = 1
group by CREATE_DATE