JOIN в месяце и году DATEPART вызывает дополнительные строки

У меня есть две таблицы, содержащие поле даты. Это поле даты является одной из причин ПРИСОЕДИНЕНИЯ, которую я хотел бы реализовать, но я хочу ПРИСОЕДИНЯТЬСЯ только к месяцу и году, а не к дню. Количество записей примерно утроится, когда я попытаюсь это сделать. Я предполагаю, что что-то не так с моим запросом? Или это вообще возможно? Я использую Постгрес

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);

Я пытаюсь получить конвертацию валюты на основе дат (только месяц и год) в каждой из таблиц. Некоторые конвертации валют отличаются (оператор CASE для поля net_value_trans_currency_netwr). Я хочу, чтобы поле net_value_trans_currency_netwr было новой строкой, отображающей конвертацию валюты в доллары США. Исходная таблица содержит более 5 миллионов строк. После соединений я получаю гораздо больше строк. Из того, что я понимаю, я получаю полное соединение. Как я смогу выполнить то, что я пытаюсь сделать, без полного соединения, создающего больше, чем нужно, строк?


person user3329160    schedule 17.03.2014    source источник
comment
Я не очень удивлен, что вы получаете больше строк, когда делаете условие соединения менее строгим. Но вы должны показать нам некоторые примеры данных, вывод и объяснить, почему этот вывод неверен.   -  person a_horse_with_no_name    schedule 18.03.2014
comment
вам нужно отредактировать условие присоединения к оператору case, если год = год, а затем присоединиться к месяцу. он устраняет дубликаты, переходя из года в год. я предлагаю вам добавить еще один, где существует.   -  person Mahesh Sambu    schedule 18.03.2014
comment
Нужно их как-то сгруппировать. Не могу помочь, не зная больше. Некоторые примеры данных и ожидаемый результат.   -  person Tony Hopkinson    schedule 18.03.2014
comment
Итак, количество записей в таблице подскочило с 6 168 781 до 19 022 763 после создания соединения. Вот и думаю, что что-то не так.   -  person user3329160    schedule 18.03.2014
comment
Вот полный код, который я написал, чтобы заставить его работать:   -  person user3329160    schedule 19.03.2014
comment
Отредактированный исходный вопрос выше ^   -  person user3329160    schedule 19.03.2014
comment
Есть ли в вашей таблице валют несколько строк (с курсами) для одной валюты за один месяц? (т.е., возможно, скорость меняется в зависимости от дня?)   -  person sarin    schedule 19.03.2014
comment
Он содержит несколько строк для одной валюты (например, доллара США) за один месяц. Но он содержит снимки за несколько месяцев, а не ежедневные изменения.   -  person user3329160    schedule 19.03.2014


Ответы (2)


Вы получаете повторяющиеся строки, поскольку вы ВНУТРЕННЕЕ СОЕДИНЕНИЕ в месяце и году, которые не являются уникальными. Это вызывает перекрестное соединение, например.

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)

Если вы хотите избежать этого, вам нужно включить в соединение что-то еще, что сделает каждое соединение уникальным! Добавление дня может помочь, но опять же, если у вас есть более одной даты, записанной в один и тот же день, вы получите дубликат. Подумайте, что еще вы могли бы включить в соединение.

person sarin    schedule 17.03.2014
comment
Это имеет смысл. Спасибо, я посмотрю на это. - person user3329160; 18.03.2014
comment
Нет проблем. Если вы считаете, что это полезно, выберите мой пост как ответ на ваш вопрос! - person sarin; 18.03.2014
comment
У меня нет других уникальных полей для использования в качестве предложений соединения. Как я могу сравнить месяц/год по-другому? - person user3329160; 19.03.2014
comment
Итак, из обновленного запроса у вас есть список транзакций в таблице A (src.sap_vbak) и валюта в таблице B (src.sap_tcurr). Есть ли в src.sap_vbak что-нибудь, что могло бы определить, какая валюта используется, например. столбец «Местоположение»? Если нет, я предполагаю, что вы хотите получить правильную валюту для своей транзакции. Как узнать, какая валюта применяется к транзакции (т. е. в каких столбцах содержится эта информация)? Без этой информации мы не сможем продвигаться вперед. - person sarin; 19.03.2014
comment
Да, это правильно. Поля, к которым у меня сейчас есть соединение, src.sap_vbak.waerk и src.sap_tcurr — это тип валюты. то есть доллары США или иены. - person user3329160; 19.03.2014

Используйте 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);

Кроме того, вы, вероятно, захотите еще больше ограничить объединение. Это ограниченное перекрестное соединение, приводящее к декартову произведению. . Если у вас есть 3 строки для марта 2014 года в tableA и 4 строки для марта 2014 года в tableB, вы уже получаете 12 строк в результате.

person Erwin Brandstetter    schedule 17.03.2014
comment
@ user3329160: Конечно, просто проще и быстрее. Вам необходимо определить дополнительные условия, какие строки из tableA присоединяются к какой строке из tableB. - person Erwin Brandstetter; 19.03.2014
comment
Нет никаких других условий, которые объединяют две таблицы вместе. - person user3329160; 19.03.2014
comment
@ user3329160: Затем вам нужно уменьшить количество строк в месяц до 1 на одной из двух сторон, в подвыборке или CTE. С GROUP BY или DISTINCT ON... У меня недостаточно информации, чтобы сказать больше. - person Erwin Brandstetter; 19.03.2014