对于以下示例,VOLUME_ON
,VOLUME_OFF
,COST_TYPE
可以是一组特定值(注意VOLUMES_ON/OFF
值与COST_TYPE
值不同)
CREATE TABLE PROJECT (
PROJECT_ID VARCHAR2 (10),
NAME VARCHAR2(10),
PRIMARY KEY (PROJECT_ID)
);
CREATE TABLE PROJECT_COSTS (
COST_ID VARCHAR2 (10),
COST_TYPE VARCHAR2 (10),
PRIMARY KEY (COST_ID)
);
CREATE TABLE PROJECT_DETAILS (
DETAIL_ID VARCHAR2 (10),
VOLUME_ON VARCHAR2(10),
VOLUME_OFF VARCHAR2(10),
PRJ_ID VARCHAR2 (10) FOREIGN KEY
REFERENCES PROJECT(PROJECT_ID),
CST_ID FOREIGN KEY
REFERENCES PROJECT_COSTS(COST_ID)
);
对于每个PROJECT.PROJECT_ID
,我想计算VOLUME_ON
中某些值VOLUME_OFF
,COST_TYPE
的出现次数。有点像。
SELECT COUNT(VOLUME_ON),
COUNT(VOLUME_OFF),
COUNT(TBC.VOLUME_ON),
COUNT(TBC.VOLUME_OFF)
FROM PROJECT p
LEFT JOIN PROJECT_DETAILS pd ON p.PROJECT_ID = pd.PROJECT_ID
LEFT JOIN PROJECT_COSTS pc ON pd.CST.ID = pc.COST_ID
AND pc.COST_TYPE IN ('ab', 'cd')
LEFT JOIN PROJECT_COSTS pc2 ON pd.CST.ID = pc2.COST_ID
AND pc2.COST_TYPE IN ('ef', 'gh')
GROUP BY p.PROJECT_ID
如何为每个VOLUME_ON
的不同COST_TYPE返回VOLUME_OFF
和PROJECT_ID
的计数?
答案 0 :(得分:0)
您可以通过在COST_TYPE
子句中添加COST_TYPE
为每个GROUP BY
生成单独的计数。您还应该将项目和成本类型信息添加到输出中,这样您就可以区分不同的项目/成本类型。
如,
SELECT p.name,
pc.cost_type,
COUNT(VOLUME_ON),
COUNT(VOLUME_OFF),
COUNT(TBC.VOLUME_ON),
COUNT(TBC.VOLUME_OFF)
FROM PROJECT p
LEFT JOIN PROJECT_DETAILS pd
ON p.PROJECT_ID = pd.PROJECT_ID
LEFT JOIN PROJECT_COSTS pc
ON pd.CST.ID = pc.COST_ID
AND pc.COST_TYPE IN ('ab', 'cd')
LEFT JOIN PROJECT_COSTS pc2
ON pd.CST.ID = pc2.COST_ID
AND pc2.COST_TYPE IN ('ef', 'gh')
GROUP BY p.PROJECT_ID, pc.cost_type
答案 1 :(得分:0)
我认为这是一个显示"左连接常数"问题。
通常,在语义上加入常量不是真正需要的。在此示例中,我们应该在COST_TYPE上过滤,而不是加入COST_TYPE。为什么这很重要?因为他们给出不同的结果!这可以通过示例来显示。让我们在这个例子中添加一些数据:
drop table project_details;
drop table project_costs;
drop table project;
CREATE TABLE PROJECT (
PROJECT_ID VARCHAR2 (10),
NAME VARCHAR2(10),
PRIMARY KEY (PROJECT_ID)
);
CREATE TABLE PROJECT_COSTS (
COST_ID VARCHAR2 (10),
COST_TYPE VARCHAR2 (10),
PRIMARY KEY (COST_ID)
);
CREATE TABLE PROJECT_DETAILS (
DETAIL_ID VARCHAR2 (10),
VOLUME_ON VARCHAR2(10),
VOLUME_OFF VARCHAR2(10),
PRJ_ID VARCHAR2 (10),
CST_ID VARCHAR2(10),
FOREIGN KEY (PRJ_ID) REFERENCES PROJECT(PROJECT_ID),
FOREIGN KEY (CST_ID ) REFERENCES PROJECT_COSTS(COST_ID)
);
insert into project values( '1', 'Proj1' );
insert into project values( '2', 'Proj2' );
insert into project values( '3', 'Proj3' );
insert into project values( '4', 'Proj4' );
commit;
insert into project_costs values( 'C1', 'ab' );
insert into project_costs values( 'C2', 'cd' );
insert into project_costs values( 'C3', 'ef' );
insert into project_costs values( 'C4', 'gh' );
insert into project_costs values( 'C5', 'zz' );
commit;
insert into project_details values( 'D1', 'V1', 'V2', '1','C1' );
insert into project_details values( 'D2', 'V1', 'V2', '1','C2' );
insert into project_details values( 'D3', 'V1', 'V2', '1','C3' );
insert into project_details values( 'D4', 'V1', 'V2', '2','C1' );
insert into project_details values( 'D5', 'V1', 'V2', '3','C1' );
insert into project_details values( 'D6', 'V1', 'V2', '1','C1' );
commit;
暂时忽略聚合,只执行连接...
SELECT p.name
, pc.cost_id
, pc.cost_type
, pd.detail_id
FROM PROJECT p
LEFT JOIN PROJECT_DETAILS pd
ON p.PROJECT_ID = pd.PRJ_ID
LEFT JOIN PROJECT_COSTS pc
ON pd.CST_ID = pc.COST_ID
AND pc.COST_TYPE IN ('ab', 'cd')
NAME COST_ID COST_TYPE DETAIL_ID
---------- ---------- ---------- ----------
Proj1 C1 ab D6
Proj3 C1 ab D5
Proj2 C1 ab D4
Proj1 C1 ab D1
Proj1 C2 cd D2
Proj4
Proj1 D3
7 rows selected.
您可以看到我们在"加入"之后得到左连接生成的其他行。在COST_TYPE上(' ab',' cd')。如果我们将JOIN更改为过滤器...
SELECT p.name
, pc.cost_id
, pc.cost_type
, pd.detail_id
FROM PROJECT p
LEFT JOIN PROJECT_DETAILS pd
ON p.PROJECT_ID = pd.PRJ_ID
LEFT JOIN PROJECT_COSTS pc
ON pd.CST_ID = pc.COST_ID
WHERE pc.COST_TYPE IN ('ab', 'cd') <--- Now a filter
NAME COST_ID COST_TYPE DETAIL_ID
---------- ---------- ---------- ----------
Proj1 C1 ab D1
Proj1 C2 cd D2
Proj2 C1 ab D4
Proj3 C1 ab D5
Proj1 C1 ab D6
由于我们已经定义了PROJECT_DETAILS
和PROJECT_COSTS
之间的关系,因此我们知道每个PROJECT_DETAIL
记录必须具有PROJECT_COST
,因此不需要LEFT OUTER连接。实际上,优化器会将计划转换为使用内连接。
所以最后,我认为查询看起来应该像
SELECT p.name
, pc.cost_type
, count(pd.volume_on)
, count(pd.volume_off)
FROM PROJECT p
LEFT JOIN PROJECT_DETAILS pd
ON p.PROJECT_ID = pd.PRJ_ID
LEFT JOIN PROJECT_COSTS pc
ON pd.CST_ID = pc.COST_ID
where pc.COST_TYPE IN ('ab', 'cd', 'ef', 'gh')
group by p.name
, pc.cost_type
order by 1,2
NAME COST_TYPE COUNT(PD.VOLUME_ON) COUNT(PD.VOLUME_OFF)
---------- ---------- ------------------- --------------------
Proj1 ab 2 2
Proj1 cd 1 1
Proj1 ef 1 1
Proj2 ab 1 1
Proj3 ab 1 1
但是,我在这里要强调的重要一点是,OUTER连接中ON子句和WHERE子句之间的语义差异。