美好的一天。
我有下表:
我创建了一个名为 AVG_COMPLETION_TIME_FACT 的表,并希望使用与前3个表有关的以下值填充该表:
我有以下无效的代码:
INSERT INTO AVG_COMPLETION_TIME_FACT(
SELECT PRODUCT_ID, EXTRACT (YEAR FROM INVOICE_DATE), EXTRACT (MONTH FROM INVOICE_DATE), (INVOICE_DATE - ORDER_DATE)
FROM STOCK, INVOICE_HEADER, ORDER_HEADER
GROUP BY PRODUCT_ID, EXTRACT (YEAR FROM INVOICE_DATE), EXTRACT (MONTH FROM INVOICE_DATE)
);
我想按product_id,发票年份和发票月份分组。
这可能吗?
任何建议将不胜感激。
致谢
答案 0 :(得分:0)
简短的回答:有可能-如果您的数据库包含编写正确查询所需的更多列。
除了语法上的问题外,还有几个问题。当我们创建一些测试表时,您会发现所需的答案无法从问题中提供的列中得出。示例表(Oracle 12c),省略了所有PK / FK约束:
-- 3 tables, similar to the ones described in your question,
-- including some test data
create table order_header (id, customer_id, agent_id, order_date )
as
select 1000, 100, 1, date'2018-01-01' from dual union all
select 1001, 100, 2, date'2018-01-02' from dual union all
select 1002, 100, 3, date'2018-01-03' from dual
;
create table invoice_header ( id, customer_id, agent_id, invoice_date )
as
select 2000, 100, 1, date'2018-02-01' from dual union all
select 2001, 100, 2, date'2018-03-11' from dual union all
select 2002, 100, 3, date'2018-04-21' from dual
;
create table stock( product_id, product_description)
as
select 3000, 'product3000' from dual union all
select 3001, 'product3001' from dual union all
select 3002, 'product3002' from dual
;
如果按照完成的方式联接表(使用交叉联接),则会看到比预期多的行...但是:invoice_header表和order_header表均不包含任何PRODUCT_ID数据。因此,我们无法确定哪些product_id与存储的order_id或invoice_id相关。
select
product_id
, extract( year from invoice_date )
, extract( month from invoice_date )
, invoice_date - order_date
from stock, invoice_header, order_header -- cross join -> too many rows in the resultset!
-- group by ...
;
...
27 rows selected.
为使查询正确,您可能应该编写INNER JOIN和条件(关键字:ON)。如果我们尝试使用您的原始表定义(如您的问题中所述)执行此操作,您将看到我们无法联接所有3个表,因为它们不包含所有需要的列:PRODUCT_ID(表STOCK)无法与ORDER_HEADER或INVOICE_HEADER。
这两个表(ORDER_HEADER和INVOICE_HEADER)的一个共同点是customer_id,但这不足以回答您的问题。但是,我们可以使用它来演示如何编写JOIN。
select
-- product_id
IH.customer_id as cust_id
, OH.id as OH_id
, IH.id as IH_id
, extract( year from invoice_date ) as year_
, extract( month from invoice_date ) as month_
, invoice_date - order_date as completion_time
from invoice_header IH
join order_header OH on IH.customer_id = OH.customer_id
-- the stock table cannot be joined at this stage
;
缺少列: 请将以下内容视为“概念验证”代码。假设在数据库中的某个地方,您的表中的列具有{1}链接STOCK和ORDER_HEADER(此处为STOCK_ORDER)和{2}链接ORDER_HEADER和INVOICE_HEADER(此处为ORDER_INVOICE),则实际上可以获取所需的信息。
-- each ORDER_HEADER is mapped to multiple product_ids
create table stock_order
as
select S.product_id, OH.id as oh_id -- STOCK and ORDER_HEADER
from stock S, order_header OH ; -- cross join, we use all possible combinations here
select oh_id, product_id
from stock_order
order by OH_id
;
PRODUCT_ID OH_ID
---------- ----------
3000 1000
3000 1001
3000 1002
3001 1000
3001 1001
3001 1002
3002 1000
3002 1001
3002 1002
9 rows selected.
-- each INVOICE_HEADER mapped to a single ORDER_HEADER
create table order_invoice ( order_id, invoice_id )
as
select 1000, 2000 from dual union all
select 1001, 2001 from dual union all
select 1002, 2002 from dual
;
对于查询,请确保您编码了正确的JOIN条件(ON ...),例如
-- example query. NOTICE: conditions in ON ...
select
S.product_id
, IH.customer_id as cust_id
, OH.id as OH_id
, IH.id as IH_id
, extract( year from invoice_date ) as year_
, extract( month from invoice_date ) as month_
, invoice_date - order_date as completion_time
from invoice_header IH
join order_invoice OI on IH.id = OI.invoice_id -- <- new "link" table
join order_header OH on OI.order_id = OH.id
join stock_order SO on OH.id = SO.OH_id -- <- new "link" table
join stock S on S.product_id = SO.product_id
;
现在,您可以添加GROUP BY,然后仅选择所需的列。与INSERT结合使用,您应该编写类似...
-- example avg_completion_time_fact table.
create table avg_completion_time_fact (
product_id number
, year_ number
, month_ number
, avg_completion_time number
) ;
insert into avg_completion_time_fact ( product_id, year_, month_, avg_completion_time )
select
S.product_id
, extract( year from invoice_date ) as year_
, extract( month from invoice_date ) as month_
, avg( invoice_date - order_date ) as avg_completion_time
from invoice_header IH
join order_invoice OI on IH.id = OI.invoice_id
join order_header OH on OI.order_id = OH.id
join stock_order SO on OH.id = SO.OH_id
join stock S on S.product_id = SO.product_id
group by S.product_id, extract( year from invoice_date ), extract( month from invoice_date )
;
AVG_COMPLETION_TIME_FACT表现在包含:
SQL> select * from avg_completion_time_fact order by product_id ;
PRODUCT_ID YEAR_ MONTH_ AVG_COMPLETION_TIME
---------- ---------- ---------- -------------------
3000 2018 3 68
3000 2018 4 108
3000 2018 2 31
3001 2018 3 68
3001 2018 2 31
3001 2018 4 108
3002 2018 3 68
3002 2018 4 108
3002 2018 2 31
由于我们不知道数据库所包含的所有表的定义,因此尚不清楚数据库(或架构)的最终查询将是什么样。但是,如果应用这些技术并坚持使用示例的语法,则应该能够获得所需的结果。祝你好运!