簡體   English   中英

如何在SQL中不執行笛卡爾積的情況下連接兩個表

[英]How to join two tables without performing Cartesian product in SQL

我有 ID 的 index_date 信息,我想提取基線(index_date 和 Index_date 之間的信息減去 6 個月)。 我想在不使用笛卡爾積的情況下做到這一點。

總表

ID index_date detail
1  01Jan2012  xyz
1  01Dec2011  pqr
1  01Nov2010  pqr
2  26Feb2013  abc
3  02Mar2013  abc
3  02Feb2013  ert
3  02Jan2013  tyu
4  07May2015  rts

我有一個從 Total 中提取的表 A,它具有 index_dates:

ID index_date index_detail
1  01Jan2012  xyz
2  26Feb2013  abc
3  02Mar2013  abc
4  07May2015  rts

我想從 Total 表 Table want 中提取 A 中 ID 的基線期數據:

ID date index_date detail index_detail
1  01Jan2012 01Jan2012 xyz xyz
1  01Dec2011 01Jan2012 pqr xyz
2  26Feb2013 26Feb2013 abc abc
3  02Mar2013 02Mar2013 abc abc
3  02Feb2013 02Mar2013 ert abc
3  02Jan2013 02Mar2013 tyu abc
4  07May2015 07May2015 rts rts

使用的代碼:

create table want as 
select a.* , b.date,b.detail
    from table_a as a 
    right join 
    Total as b
on a.id = b.id where
 a.index_date > b.date 
    AND  b.date >= add_months( a.index_date, -6)
;

但這需要笛卡爾積。 有沒有辦法在不需要笛卡爾積的情況下做到這一點。

數據庫管理系統-蜂巢

對不起,我不知道。

我將提供有關 MySQL 8+ 的純 SQL 的解決方案 - 也許您會找到將其轉換為 Hive 語法的方法。

SELECT id, 
       index_date date,
       FIRST_VALUE(index_date) OVER (PARTITION BY ID ORDER BY STR_TO_DATE(index_date, '%d%b%Y') DESC) index_date,
       detail,
       FIRST_VALUE(detail) OVER (PARTITION BY ID ORDER BY STR_TO_DATE(index_date, '%d%b%Y') DESC) index_detail
FROM test
ORDER BY 1 ASC, 2 DESC

小提琴

我會推薦三個步驟:

  1. 將日期轉換為數字。
  2. 找出六個月內的最短日期。
  3. 獲取該組中的第一個值。

這看起來像:

select t.*, t2.index_date, t2.detail
from (select t.*,
             min(index_date) over (partition by id
                                   order by months
                                   range between 6 preceding and current row
                                  ) as sixmonth_date
      from (select t.*,
                   year(index_date) * 12 + month(index_date) as months
            from total t
           ) t
     ) t left join
     total t2
     on t2.id = t.id and t2.index_date = t.sixmonth_date;

如果first_value()接受range窗口框架,這稍微簡單first_value() ——但我不確定它是否確實如此。 不過值得一試:

select t.*,
       min(index_date) over (partition by id
                             order by months
                             range between 6 preceding and current row
                            ) as sixmonth_date,
       first_value(detail) over (partition by id
                                 order by months
                                 range between 6 preceding and current row
                                ) as sixmonth_value
      from (select t.*,
                   year(index_date) * 12 + month(index_date) as months
            from total t
           ) t

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM