为什么我的记录计数因左连接而爆炸?

时间:2018-01-25 01:52:38

标签: sql-server tsql

如果我这样做:

Select *
FROM RAW_DATA
WHERE Portfolio like '%deposit%'

我收到了131047条记录。现在,我加入另一个表,我想要来自RAW_DATA的所有记录和来自另一个表的匹配,如下所示:

Select *
FROM RAW_DATA AS RawData LEFT OUTER JOIN
DATAHIST AS HIST ON RawData.Parse2 = HIST.CONTACT_ID AND RawData.AsofDate = HIST.ASOFDATE
WHERE RawData.Portfolio like '%deposit%'

现在,我的计数一直升至158745.如果我想要Raw_Data中的所有内容以及DATAHIST中的匹配项,我该如何创建连接线?这里只有几个选项。

我是否必须计算行数,并选择rn = 1的位置?

2 个答案:

答案 0 :(得分:3)

确定哪个HIST数据在您的连接键中有重复(重复)(id和日期的组合)。您还应该检查RAW数据中的重复项。具有重复项的每个键将对选择

产生n×m影响
drop table #RAW
drop table #HIST

create table #RAW (contact_id int, asofdate date);
insert into #RAW values 
  (1, '2017-01-01'),
  (2, '2017-01-01')

create table #HIST (contact_id int, asofdate date, balance int);
insert into #HIST values 
  (1, '2017-01-01', 100), (1, '2017-01-01', 150), (1, '2017-01-02', 200),
  (2, '2017-01-01', 125)

--select * from #RAW
--select * from #HIST

-- find duplicates in HIST
select distinct contact_id, asofdate, count(*) as occur_count
from #HIST
group by contact_id, asofdate
having count(*) > 1

-- because of the duplicates the result has 3 rows instead of the 2 you might be expecting
select raw.contact_id, raw.asofdate, hist.balance
from #raw raw left join #hist hist 
  on raw.contact_id = hist.contact_id and raw.asofdate = hist.asofdate

您可能希望通过聚合或进一步选择条件来清理数据或减少数据(每个dlatikay)

答案 1 :(得分:1)

任何源行只有1行的历史记录表非常无用,因为历史记录表通常包含每行源数据的所有历史记录。所以你应该期望扩展行数。

我怀疑你想要的是"最近的条目"历史,并且为了这样的需要,它将有助于在加入之前对行进行编号,如下所示:

SELECT
      *
FROM RAW_DATA AS rawdata
LEFT OUTER JOIN (
      SELECT
            *
          , row_number() (PARTITION BY CONTACT_ID
                           ORDER BY ASOFDATE DESC) AS rn
      DATAHIST
) AS hist ON rawdata.Parse2 = hist.CONTACT_ID
      AND hist.rn = 1
WHERE rawdata.Portfolio LIKE '%deposit%'

因此,如果历史记录中有任何一行rawdata,那么它只允许加入历史表中最近的匹配行。

改变顺序,以影响连接哪些行。例如通过更改为升序,您将获得最早的"历史而不是"最新"。如果asofdate列足够,请将其他列添加为断路器,例如order by asofdate desc, ID desc