【问题标题】:JOIN on DATEPART month and year is causing extra rowsDATEPART 月份和年份的 JOIN 导致额外的行
【发布时间】:2014-04-23 09:12:59
【问题描述】:

我有两个包含日期字段的表。这个日期字段是我想要实现的 JOIN 原因之一,但我只想在月份和年份上加入,而不是在日期上。当我尝试这样做时,记录的数量约为三倍。我猜我的查询有问题?或者这甚至可能吗?我正在使用 Postgres

SELECT a.load_date , a.mandt, a.vbeln,a.posnr, a.matnr, b.tfed
FROM tableA a
JOIN tableB b
ON date_part('month'::text, a.erdat) = date_part('month'::text, b.gdatu)
AND date_part('year'::text, a.erdat) = date_part('year'::text, b.gdatu)

编辑这是我的完整代码

 SELECT a.mandt, a.vbeln, 
   a.erdat, a.erzet, a.ernam, a.angdt, a.audat, a.vbtyp, a.trvog, 
   a.auart, a.submi, a.lifsk, a.faksk, a.netwr, a.waerk, a.vkorg, a.vtweg, a.spart, 
   a.vkgrp, a.vkbur, a.knumv, a.vdatu, a.vprgr, a.kalsm, a.vsbed, a.fkara, a.awahr, 
   a.bstnk, a.bstdk, a.telf1, a.kunnr, a.stafo, a.stwae, a.aedat, a.kvgr1,a.kvgr2, 
   a.kvgr3, a.kokrs, a.kkber, a.knkli, a.sbgrp, a.ctlpc, a.cmwae, a.cmfre, a.cmngv, 
   a.amtbl, a.hityp_pr, a.abrvw, a.vgbel, a.objnr, a.bukrs_vf, a.taxk1,a.xblnr, 
   a.vgtyp, a.abhod, a.abhov, a.stceg_l, a.landtx, a.fmbdat, a.vsnmr_v, a.handle, 
   a.yybcawv1, a.yybcawv2, a.yybcawv3, a.yyawv1dat, a.yyawv2dat, a.yybcawvc, 
   a.kvgr5, a.augru, a.autlf, a.bname, a.bnddt, a.bsark, a.cmnup, a.fiscalper,              
   a.fiscalyr, a.gwldt, a.ihrez, a.intind, a.intsum, a.rplnr, a.taxk2, a.yybabt, 
   a.yybemail, a.yybfax, a.yybname, a.yybphone, a.yyexporter, a.yypaypal_id, 
   a.yysd_projid, a.zone, a.zuonr, a.zz_campaign_id, a.zzedate, a.zzrev_cat_01, 
   a.zzrev_cat_02, a.zzrev_cat_03, a.zzrev_cat_04, a.zzrev_cat_05, a.zzrev_cat_06, 
   a.zzrev_cat_07, a.zzrev_cat_08, a.zzsdate, a.mahdt,
   CASE
        WHEN b.fcurr::text = 'USD'::text THEN a.netwr
        WHEN b.fcurr::text = 'JPY'::text AND b.kurst::text = 'M'::text THEN a.netwr * b.ukurs / 10::numeric
        WHEN b.fcurr::text = 'KRW'::text AND b.kurst::text = 'M'::text THEN a.netwr * b.ukurs / 10::numeric
        WHEN b.kurst::text = 'M'::text THEN a.netwr * b.ukurs
        ELSE a.netwr
    END AS net_value_trans_currency_netwr
FROM src.sap_vbak a
JOIN src.sap_tcurr b  
ON a.waerk::text = b.fcurr::text 
AND date_part('MONTH'::text, a.erdat::timestamp with time zone) = date_part('MONTH'::text, b.gdatu::timestamp with time zone)
AND date_part('YEAR'::text, a.erdat::timestamp with time zone) = date_part('YEAR'::text, b.gdatu::timestamp with time zone);

我正在尝试根据每个表格中的日期(仅限月份和年份)进行货币换算。一些货币转换是不同的( net_value_trans_currency_netwr 字段的 CASE 语句)。我希望 net_value_trans_currency_netwr 字段成为显示美元货币转换的新行。原始表有超过 500 万行。加入后,我得到了更多的行。从我收集到的信息来看,我得到了一个完整的加入。如果没有完全连接创建超过需要的行,我将如何执行我正在尝试做的事情?

【问题讨论】:

  • 当您使联接条件不那么严格时,您获得更多行,我并不感到惊讶。但是您应该向我们展示一些示例数据、输出并解释输出错误的原因。
  • 如果年 = 年,则必须将您的加入条件编辑为案例陈述,然后在月份加入。它逐年消除重复。我建议你在存在的地方再添加一个。
  • 您需要以某种方式对它们进行分组。不知道更多就忍不住了。一些示例数据和预期输出。
  • 好吧,一旦创建连接,表中的记录数就会从 6,168,781 跳到 19,022,763。这就是为什么我认为有些地方不对劲。
  • 这是我写的、我正在尝试开始工作的完整代码:

标签: sql postgresql join cartesian-product datepart


【解决方案1】:

当您在不唯一的月份和年份进行 INNER JOINING 时,您会得到重复的行。这会导致交叉连接,例如

Example Rows with dates
   Date          Month    Year
1  01/01/2014    01       14
2  02/01/2014    01       14

Result of above join has 4 rows not 2!
1) Month from (1) Year from (1)
2) Month from (1) Year from (2)
3) Month from (2) Year from (1)
4) Month from (2) Year from (2)

如果您想避免这种情况,您需要在连接中包含其他内容,以使每个连接都独一无二!添加日期可能会有所帮助,但如果您在同一天记录了多个日期,您将再次获得重复。想一想您还可以在联接中包含哪些内容。

【讨论】:

  • 这是有道理的。谢谢,我会调查的。
  • 没有问题。如果您认为它有用,请选择我的帖子作为已回答您的问题!
  • 我没有其他独特的字段可用作连接子句。我如何能够以另一种方式比较月/年?
  • 因此,从您更新的查询中,您可以得到表 A (src.sap_vbak) 中的交易列表和表 B (src.sap_tcurr) 中的货币。 src.sap_vbak 中是否有任何内容可以识别正在使用的货币,例如位置列?如果不是,我假设您想为您的交易获得正确的货币。您如何判断交易适用于哪种货币(即哪些列向我们提供了该信息)?如果没有这些信息,我们将无法取得进展。
  • 是的,没错。我目前加入的字段 src.sap_vbak.waerk 和 src.sap_tcurr 是货币类型。即美元或日元。
【解决方案2】:

使用date_trunc() 简化查询:

SELECT a.load_date, a.mandt, a.vbeln,a.posnr, a.matnr, b.tfed
FROM   tableA a
JOIN   tableB b ON date_trunc('month', a.erdat)
                 = date_trunc('month', b.gdatu);

另外,您可能希望进一步限制连接。这是一个有限的交叉连接,导致Cartesian product。如果您在 tableA 中有 3 行 2014 年 3 月,在 tableB 中有 4 行 2014 年 3 月,那么您已经在结果中生成了 12 行。

【讨论】:

  • @user3329160:当然可以,只是更简单、更快。您需要定义额外的条件,来自tableA 的行连接来自tableB 的行。
  • 没有其他条件可以将两个表连接在一起。
  • @user3329160:然后您必须在子选择或 CTE 中将两侧之一的每月行数减少到 1。使用GROUP BYDISTINCT ON ...我没有足够的信息可以说更多。
猜你喜欢
  • 1970-01-01
  • 2016-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-05
  • 1970-01-01
  • 2020-12-29
  • 2016-07-31
相关资源
最近更新 更多