使用相同的密钥将多个 table 连接到一个基 table
Join multiple table to one base table using the same Keys
我目前正在为来自 Oracle 的大量财务报告编写 SQL 查询。此信息对于问题不是必需的,但可以提供一些背景信息:我基本上是从特定时间范围内获取所有 gl_JEs 并将它们分解为实际交易。
所以我生成了 6 个不同的子 table 和一个基础 table.
基础table包含生成PK的两个key和一些通用信息
Header_ID 和 Line_Num
每个子table 记录还包含这两个键和附加信息。 base table 和 subtable 之间可以存在一对多的关系。和一个基地的PK可以在多个subtables.
我想将这 6 个 table 连接在一起,保留基础的一般信息并添加子 table 的信息。我可以使用 Union ALL 来做到这一点,但这意味着我必须在每个子 table 上放置相同的字段,并且我必须加入很多字段,所以这不是最优的。
这里有一些示例数据,如果所有的讨论都没有意义的话。我将通过只有 3 个 sub tables:
来简化它
create table base (Header_id int,
line_num int,
period_num int);
create table subtable1 (header_id int,
line_num int,
cost int,
description varchar(50));
create table subtable2 (header_id int,
line_num int,
invoice_num int,
description varchar(50));
create table subtable3 (header_id int,
line_num int,
value int,
description varchar(50));
Insert into base values
(1, 1 , 4),
(1,2,4),
(2,5,4),
(2,4,4),
(3,1,4),
(4,2,5);
Insert into subtable1 values
(1, 1, 50, 'Boat'),
(1, 1, 30, 'lifejacket'),
(2, 4, 4000, 'lifeinsurance');
Insert into subtable2 values
(1, 1, 89756, 'Boat supplies')
(2,5, 5464, 'fake invoice');
Insert into subtable3 values
(1, 2, 100, 'im running out')
(3, 1, 25, 'of ideas');
我想要 return 这样的东西。请忽略我缺少 nulls/field 个名字
1. 1,1,4,50,'BOAT'
2. 1,1,4,30,'lifejacket'
3. 1,1,4,89756, 'boat supplies'
4. 1,2,4,100,'im running out'
5. 2,5,4,5464,'fake invoice'
6. 2,4,4,4000,'lifeinsurance'
7. 3,1,4,25,'of ideas'
8. 4,2,5
有什么想法吗?
编辑:这是我现在的实际查询:
With
base as
(
SELECT
gjH.PERIOD_NAME Period
,gcc.SEGMENT1 || '-' || gcc.SEGMENT2 || '-' || gcc.SEGMENT3 || '-' || gcc.SEGMENT4 || '-' || gcc.SEGMENT5 || '-' || gcc.SEGMENT6 GL_COA
,gjL.JE_HEADER_ID
,gjL.JE_LINE_NUM
,gp.period_num
,gp.period_year
,gjh.date_created
,gjh.default_effective_date
,gjh.currency_code base_currency_code
,gjh.currency_code transaction_currency_code
FROM
apps.GL_JE_Batches gjB
,apps.GL_JE_HEADERS gjH
,apps.GL_JE_LINES gjL
,apps.gl_code_combinations gcc
,apps.gl_periods gp
WHERE
gjB.je_batch_id = gjH.JE_BATCH_ID
and gjH.JE_HEADER_ID = gjL.JE_HEADER_ID
and gjH.PERIOD_NAME in (:period, :period2, :period3)
AND gjl.CODE_COMBINATION_ID = gcc.CODE_COMBINATION_ID
and (gjL.accounted_dr != 0 OR gjL.accounted_cr != 0)
and gjH.Period_Name = gp.Period_Name
)
,Subledger as -- Not all Base records have a Subledger record! 58825
( -- Return all the primary keys for the Subledger and then the FK to the different distribution tables,
SELECT
base.period Period
,base.GL_COA GL_COA
,base.JE_Header_ID
,base.JE_Line_NUM
,base.period_num
,base.period_year
,base.date_created
,base.default_effective_date
,base.base_currency_code
,base.transaction_currency_code
,xal.GL_SL_LINK_TABLE
,xal.GL_SL_LINK_ID
,xal.ae_line_num
,xah.ae_header_id
,xah.application_id
,xe.event_id
,xte.entity_id
,xdl.SOURCE_DISTRIBUTION_TYPE --Tells you what table to pull lines/info from
,xdl.SOURCE_DISTRIBUTION_ID_NUM_1 --Is the FK ID to the above distribution table.
,decode(nvl(xdl.unrounded_accounted_dr,0),0,xdl.unrounded_accounted_cr,-1*xdl.unrounded_accounted_dr) base_amount
,decode(nvl(xdl.unrounded_accounted_dr,0),0,xdl.unrounded_accounted_cr,-1*xdl.unrounded_accounted_dr) transaction_amount
FROM
base
,apps.gl_import_references gRef
,xla.xla_ae_lines xal
,xla.xla_ae_headers xah
,xla.xla_events xe
,xla.xla_transaction_entities xte
,xla.xla_distribution_links xdl
WHERE
base.JE_HEADER_ID = gRef.JE_HEADER_ID
AND base.JE_LINE_NUM = gRef.JE_LINE_NUM
AND gRef.GL_SL_LINK_TABLE = xal.GL_SL_LINK_TABLE
AND gRef.GL_SL_LINK_ID = xal.GL_SL_LINK_ID
and xal.AE_HEADER_ID = xah.ae_header_id
and xal.APPLICATION_ID = xah.APPLICATION_ID
and xah.AE_HEADER_ID = xdl.AE_HEADER_ID
and xal.AE_LINE_NUM = xdl.AE_LINE_NUM
and xah.event_id = xe.event_id
and xah.application_id = xe.application_id
and xe.entity_id = xte.entity_id
and xe.APPLICATION_ID = xte.APPLICATION_ID
)
,AP_PMT_DIST as --5476
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_Header_ID
,sl.JE_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'AP_PMT_DIST' || '|' || apid.description description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.Transaction_currency_code
FROM
subledger sl
,AP.AP_PAYMENT_HIST_DISTS aphd
,AP.AP_INVOICE_DISTRIBUTIONS_ALL apid
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'AP_PMT_DIST'
AND sl.SOURCE_DISTRIBUTION_ID_NUM_1 = aphd.payment_hist_dist_id
and apid.invoice_distribution_id = aphd.invoice_distribution_id
)
,AP_INV_DIST as --4422
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_header_id
,sl.je_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'AP_INV_DIST' || '|' || apid.description description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.Transaction_currency_code
FROM
subledger sl
,AP.AP_INVOICE_DISTRIBUTIONS_ALL apid
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'AP_INV_DIST'
AND sl.SOURCE_DISTRIBUTION_ID_NUM_1 = apid.INVOICE_DISTRIBUTION_ID
)
,AP_PREPAY as --10 records
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_header_id
,sl.je_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'AP_PREPAY' || '|' || apid.description description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.Transaction_currency_code
FROM
subledger sl
,AP.AP_PREPAY_APP_DISTS appad
,AP.AP_Invoice_distributions_all apid
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'AP_PREPAY'
AND sl.SOURCE_DISTRIBUTION_ID_NUM_1 = appad.PREPAY_APP_DIST_ID
AND appad.Invoice_distribution_id = apid.invoice_distribution_id
)
,AR_DIST as --34321 records
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_header_id
,sl.je_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'AR Invoice Line' description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.Transaction_currency_code
FROM
subledger sl
,AR.AR_DISTRIBUTIONS_ALL ARDA
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'AR_DISTRIBUTIONS_ALL'
and sl.SOURCE_DISTRIBUTION_ID_NUM_1 = ARDA.line_id
)
,AR_CUST_TRX as --14596 records
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_header_id
,sl.je_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'Cust_Trx_Line' description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.transaction_currency_code
FROM
subledger sl
,AR.RA_CUST_TRX_LINE_GL_DIST_ALL ctld
,AR.RA_Customer_trx_lines_all ctl
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'RA_CUST_TRX_LINE_GL_DIST_ALL'
AND sl.source_distribution_id_num_1 = ctld.cust_trx_line_gl_dist_id
AND ctld.customer_trx_line_id = ctl.customer_trx_line_id (+)
--and ctld.amount <> ctl.revenue_amount
)
,spreads as
(
SELECT
b.PERIOD Period
,b.period_num
,b.period_year
,b.GL_COA
,b.JE_HEADER_ID
,b.JE_LINE_NUM
,decode(nvl(gjl.accounted_dr,0),0,gjl.accounted_cr,-1*gjl.accounted_dr) base_amount
,decode(nvl(gjl.accounted_dr,0),0,gjl.accounted_cr,-1*gjl.accounted_dr) transaction_amount
,gjH.DESCRIPTION DESCRIPTION
,b.date_created
,b.default_effective_date
,b.base_currency_code
,b.transaction_currency_code
FROM
base B
,apps.GL_JE_HEADERS gjH
,apps.GL_JE_LINES gjL
WHERE
B.JE_Header_ID = gjH.JE_Header_ID
AND B.JE_Line_Num = gjL.JE_Line_num
and gjH.JE_HEADER_ID = gjL.JE_HEADER_ID
and gjH.JE_CATEGORY = 'Adjustment'
and gjH.JE_SOURCE = 'Spreadsheet'
)
-- okay now we have all the types! and the number of records line up from the subledger distribution list.
-- Now we need to get the required information about each transaction.
-- We will need to pass: Base table linking information (JEHeader and JELine) and Information about the line.
-- Then we will join these all together.
--Okay I have a breakdown, lets first get the values and make sure it all lines up.
--select * from ar_cust_trx;
--select * from AP_INV_DIST;
SELECT * FROM AP_INV_DIST AID --4422
UNION ALL
Select * FROM AP_PMT_DIST APD --9898 5476
Union ALL
select * FROM AP_PREPAY APR --9908 10
Union ALL
select * FROM AR_DIST ARD --44229 34321
Union ALL
select * FROM AR_CUST_TRX ARC --58825 It got rid of duplicates within itself, despite the fact they arn't duplicates.
Union ALL
select * FROM spreads --60011 1186
只需使用 UNION ALL
- 大致如下:
SELECT DISTINCT * FROM
(
SELECT
base.header_id
, base.line_num
, base.period_num
, subtable1.cost col3
, subtable1.description col4
FROM
base
left join subtable1
on base.header_id = subtable1.header_id and base.line_num = subtable1.line_num
UNION ALL
SELECT
base.header_id
, base.line_num
, base.period_num
, subtable2.invoice_num
, subtable2.description
FROM
base
left join subtable2
on base.header_id = subtable2.header_id and base.line_num = subtable2.line_num
UNION ALL
...
)
我只是徒手写的,但我相信类似的东西应该可以解决问题。
希望对您有所帮助!!
我目前正在为来自 Oracle 的大量财务报告编写 SQL 查询。此信息对于问题不是必需的,但可以提供一些背景信息:我基本上是从特定时间范围内获取所有 gl_JEs 并将它们分解为实际交易。
所以我生成了 6 个不同的子 table 和一个基础 table.
基础table包含生成PK的两个key和一些通用信息 Header_ID 和 Line_Num
每个子table 记录还包含这两个键和附加信息。 base table 和 subtable 之间可以存在一对多的关系。和一个基地的PK可以在多个subtables.
我想将这 6 个 table 连接在一起,保留基础的一般信息并添加子 table 的信息。我可以使用 Union ALL 来做到这一点,但这意味着我必须在每个子 table 上放置相同的字段,并且我必须加入很多字段,所以这不是最优的。
这里有一些示例数据,如果所有的讨论都没有意义的话。我将通过只有 3 个 sub tables:
来简化它create table base (Header_id int,
line_num int,
period_num int);
create table subtable1 (header_id int,
line_num int,
cost int,
description varchar(50));
create table subtable2 (header_id int,
line_num int,
invoice_num int,
description varchar(50));
create table subtable3 (header_id int,
line_num int,
value int,
description varchar(50));
Insert into base values
(1, 1 , 4),
(1,2,4),
(2,5,4),
(2,4,4),
(3,1,4),
(4,2,5);
Insert into subtable1 values
(1, 1, 50, 'Boat'),
(1, 1, 30, 'lifejacket'),
(2, 4, 4000, 'lifeinsurance');
Insert into subtable2 values
(1, 1, 89756, 'Boat supplies')
(2,5, 5464, 'fake invoice');
Insert into subtable3 values
(1, 2, 100, 'im running out')
(3, 1, 25, 'of ideas');
我想要 return 这样的东西。请忽略我缺少 nulls/field 个名字
1. 1,1,4,50,'BOAT'
2. 1,1,4,30,'lifejacket'
3. 1,1,4,89756, 'boat supplies'
4. 1,2,4,100,'im running out'
5. 2,5,4,5464,'fake invoice'
6. 2,4,4,4000,'lifeinsurance'
7. 3,1,4,25,'of ideas'
8. 4,2,5
有什么想法吗?
编辑:这是我现在的实际查询:
With
base as
(
SELECT
gjH.PERIOD_NAME Period
,gcc.SEGMENT1 || '-' || gcc.SEGMENT2 || '-' || gcc.SEGMENT3 || '-' || gcc.SEGMENT4 || '-' || gcc.SEGMENT5 || '-' || gcc.SEGMENT6 GL_COA
,gjL.JE_HEADER_ID
,gjL.JE_LINE_NUM
,gp.period_num
,gp.period_year
,gjh.date_created
,gjh.default_effective_date
,gjh.currency_code base_currency_code
,gjh.currency_code transaction_currency_code
FROM
apps.GL_JE_Batches gjB
,apps.GL_JE_HEADERS gjH
,apps.GL_JE_LINES gjL
,apps.gl_code_combinations gcc
,apps.gl_periods gp
WHERE
gjB.je_batch_id = gjH.JE_BATCH_ID
and gjH.JE_HEADER_ID = gjL.JE_HEADER_ID
and gjH.PERIOD_NAME in (:period, :period2, :period3)
AND gjl.CODE_COMBINATION_ID = gcc.CODE_COMBINATION_ID
and (gjL.accounted_dr != 0 OR gjL.accounted_cr != 0)
and gjH.Period_Name = gp.Period_Name
)
,Subledger as -- Not all Base records have a Subledger record! 58825
( -- Return all the primary keys for the Subledger and then the FK to the different distribution tables,
SELECT
base.period Period
,base.GL_COA GL_COA
,base.JE_Header_ID
,base.JE_Line_NUM
,base.period_num
,base.period_year
,base.date_created
,base.default_effective_date
,base.base_currency_code
,base.transaction_currency_code
,xal.GL_SL_LINK_TABLE
,xal.GL_SL_LINK_ID
,xal.ae_line_num
,xah.ae_header_id
,xah.application_id
,xe.event_id
,xte.entity_id
,xdl.SOURCE_DISTRIBUTION_TYPE --Tells you what table to pull lines/info from
,xdl.SOURCE_DISTRIBUTION_ID_NUM_1 --Is the FK ID to the above distribution table.
,decode(nvl(xdl.unrounded_accounted_dr,0),0,xdl.unrounded_accounted_cr,-1*xdl.unrounded_accounted_dr) base_amount
,decode(nvl(xdl.unrounded_accounted_dr,0),0,xdl.unrounded_accounted_cr,-1*xdl.unrounded_accounted_dr) transaction_amount
FROM
base
,apps.gl_import_references gRef
,xla.xla_ae_lines xal
,xla.xla_ae_headers xah
,xla.xla_events xe
,xla.xla_transaction_entities xte
,xla.xla_distribution_links xdl
WHERE
base.JE_HEADER_ID = gRef.JE_HEADER_ID
AND base.JE_LINE_NUM = gRef.JE_LINE_NUM
AND gRef.GL_SL_LINK_TABLE = xal.GL_SL_LINK_TABLE
AND gRef.GL_SL_LINK_ID = xal.GL_SL_LINK_ID
and xal.AE_HEADER_ID = xah.ae_header_id
and xal.APPLICATION_ID = xah.APPLICATION_ID
and xah.AE_HEADER_ID = xdl.AE_HEADER_ID
and xal.AE_LINE_NUM = xdl.AE_LINE_NUM
and xah.event_id = xe.event_id
and xah.application_id = xe.application_id
and xe.entity_id = xte.entity_id
and xe.APPLICATION_ID = xte.APPLICATION_ID
)
,AP_PMT_DIST as --5476
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_Header_ID
,sl.JE_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'AP_PMT_DIST' || '|' || apid.description description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.Transaction_currency_code
FROM
subledger sl
,AP.AP_PAYMENT_HIST_DISTS aphd
,AP.AP_INVOICE_DISTRIBUTIONS_ALL apid
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'AP_PMT_DIST'
AND sl.SOURCE_DISTRIBUTION_ID_NUM_1 = aphd.payment_hist_dist_id
and apid.invoice_distribution_id = aphd.invoice_distribution_id
)
,AP_INV_DIST as --4422
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_header_id
,sl.je_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'AP_INV_DIST' || '|' || apid.description description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.Transaction_currency_code
FROM
subledger sl
,AP.AP_INVOICE_DISTRIBUTIONS_ALL apid
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'AP_INV_DIST'
AND sl.SOURCE_DISTRIBUTION_ID_NUM_1 = apid.INVOICE_DISTRIBUTION_ID
)
,AP_PREPAY as --10 records
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_header_id
,sl.je_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'AP_PREPAY' || '|' || apid.description description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.Transaction_currency_code
FROM
subledger sl
,AP.AP_PREPAY_APP_DISTS appad
,AP.AP_Invoice_distributions_all apid
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'AP_PREPAY'
AND sl.SOURCE_DISTRIBUTION_ID_NUM_1 = appad.PREPAY_APP_DIST_ID
AND appad.Invoice_distribution_id = apid.invoice_distribution_id
)
,AR_DIST as --34321 records
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_header_id
,sl.je_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'AR Invoice Line' description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.Transaction_currency_code
FROM
subledger sl
,AR.AR_DISTRIBUTIONS_ALL ARDA
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'AR_DISTRIBUTIONS_ALL'
and sl.SOURCE_DISTRIBUTION_ID_NUM_1 = ARDA.line_id
)
,AR_CUST_TRX as --14596 records
(
SELECT
sl.period
,sl.period_num
,sl.period_year
,sl.gl_coa
,sl.JE_header_id
,sl.je_line_num
,sl.base_amount base_amount
,sl.transaction_amount transaction_amount
,'Cust_Trx_Line' description
,sl.date_created
,sl.default_effective_date
,sl.base_currency_code
,sl.transaction_currency_code
FROM
subledger sl
,AR.RA_CUST_TRX_LINE_GL_DIST_ALL ctld
,AR.RA_Customer_trx_lines_all ctl
WHERE
sl.SOURCE_DISTRIBUTION_TYPE = 'RA_CUST_TRX_LINE_GL_DIST_ALL'
AND sl.source_distribution_id_num_1 = ctld.cust_trx_line_gl_dist_id
AND ctld.customer_trx_line_id = ctl.customer_trx_line_id (+)
--and ctld.amount <> ctl.revenue_amount
)
,spreads as
(
SELECT
b.PERIOD Period
,b.period_num
,b.period_year
,b.GL_COA
,b.JE_HEADER_ID
,b.JE_LINE_NUM
,decode(nvl(gjl.accounted_dr,0),0,gjl.accounted_cr,-1*gjl.accounted_dr) base_amount
,decode(nvl(gjl.accounted_dr,0),0,gjl.accounted_cr,-1*gjl.accounted_dr) transaction_amount
,gjH.DESCRIPTION DESCRIPTION
,b.date_created
,b.default_effective_date
,b.base_currency_code
,b.transaction_currency_code
FROM
base B
,apps.GL_JE_HEADERS gjH
,apps.GL_JE_LINES gjL
WHERE
B.JE_Header_ID = gjH.JE_Header_ID
AND B.JE_Line_Num = gjL.JE_Line_num
and gjH.JE_HEADER_ID = gjL.JE_HEADER_ID
and gjH.JE_CATEGORY = 'Adjustment'
and gjH.JE_SOURCE = 'Spreadsheet'
)
-- okay now we have all the types! and the number of records line up from the subledger distribution list.
-- Now we need to get the required information about each transaction.
-- We will need to pass: Base table linking information (JEHeader and JELine) and Information about the line.
-- Then we will join these all together.
--Okay I have a breakdown, lets first get the values and make sure it all lines up.
--select * from ar_cust_trx;
--select * from AP_INV_DIST;
SELECT * FROM AP_INV_DIST AID --4422
UNION ALL
Select * FROM AP_PMT_DIST APD --9898 5476
Union ALL
select * FROM AP_PREPAY APR --9908 10
Union ALL
select * FROM AR_DIST ARD --44229 34321
Union ALL
select * FROM AR_CUST_TRX ARC --58825 It got rid of duplicates within itself, despite the fact they arn't duplicates.
Union ALL
select * FROM spreads --60011 1186
只需使用 UNION ALL
- 大致如下:
SELECT DISTINCT * FROM
(
SELECT
base.header_id
, base.line_num
, base.period_num
, subtable1.cost col3
, subtable1.description col4
FROM
base
left join subtable1
on base.header_id = subtable1.header_id and base.line_num = subtable1.line_num
UNION ALL
SELECT
base.header_id
, base.line_num
, base.period_num
, subtable2.invoice_num
, subtable2.description
FROM
base
left join subtable2
on base.header_id = subtable2.header_id and base.line_num = subtable2.line_num
UNION ALL
...
)
我只是徒手写的,但我相信类似的东西应该可以解决问题。
希望对您有所帮助!!