【问题标题】:what is the best way to join two tables and use sum function连接两个表并使用 sum 函数的最佳方法是什么
【发布时间】:2019-02-17 23:17:16
【问题描述】:

我想知道,以可接受/标准的方式实现以下输出的最佳方式是什么。

我正在尝试加入两个表结果 table1 org(同一个表中的主键和外键)和表 2 许可证,我在其中使用 sum 函数。

查询的输入将是 parent_org_id 和 product 查询应该让我返回父/子组织和他们每个人的许可证计数。

在将结果与函数和 where 条件相结合时,我遇到了问题。 我已经尝试了下面提供的查询。我知道这不符合标准。

  • 我使用or 条件来绕过父子记录。
  • 我也猜想我的查询对两个表都执行了扫描,因此认为可以避免这种情况,因为这两个表都很重。

数据创建:

CREATE TABLE LICENSE (LICENSE_ID NUMBER NOT NULL PRIMARY KEY,   ORG_ID NUMBER,  QUANTITY NUMBER,    PRODUCT VARCHAR(10), START_DATE TIMESTAMP(6),   END_DATE TIMESTAMP(6));
Insert into LICENSE (LICENSE_ID,ORG_ID,QUANTITY,PRODUCT,START_DATE,END_DATE) values (1,222,10,'MOVIES', to_timestamp('01-JAN-18 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'),to_timestamp('04-JAN-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'));
Insert into LICENSE (LICENSE_ID,ORG_ID,QUANTITY,PRODUCT,START_DATE,END_DATE) values (2,222,3,'BOOKS',to_timestamp('01-JUN-18 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'),to_timestamp('18-DEC-18 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'));
Insert into LICENSE (LICENSE_ID,ORG_ID,QUANTITY,PRODUCT,START_DATE,END_DATE) values (3,222,6,'GOOGLE',to_timestamp('01-JAN-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'),to_timestamp('31-DEC-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'));
Insert into LICENSE (LICENSE_ID,ORG_ID,QUANTITY,PRODUCT,START_DATE,END_DATE) values (4,222,5, null, to_timestamp('01-JAN-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'),to_timestamp('31-DEC-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'));
Insert into LICENSE (LICENSE_ID,ORG_ID,QUANTITY,PRODUCT,START_DATE,END_DATE) values (5,222,8, null, to_timestamp('01-JAN-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'),to_timestamp('31-JAN-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'));
Insert into LICENSE (LICENSE_ID,ORG_ID,QUANTITY,PRODUCT,START_DATE,END_DATE) values (6,222,7,'BOOKS',to_timestamp('01-JAN-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'),to_timestamp('15-FEB-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'));
Insert into LICENSE (LICENSE_ID,ORG_ID,QUANTITY,PRODUCT,START_DATE,END_DATE) values (7,222,7,'MOVIES',to_timestamp('01-JAN-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'),to_timestamp('15-FEB-19 00:00:00.000000000','DD-MON-RR HH24:MI:SSXFF'));

CREATE TABLE ORG (ORG_ID NUMBER NOT NULL PRIMARY KEY, ORG_NAME VARCHAR2(10), PARENT_ORG_ID NUMBER, FOREIGN KEY (PARENT_ORG_ID) REFERENCES ORG(ORG_ID));
Insert into ORG (ORG_ID,ORG_NAME,PARENT_ORG_ID) values (111,'district-1',null);
Insert into ORG (ORG_ID,ORG_NAME,PARENT_ORG_ID) values (999,'district-2',null);
Insert into ORG (ORG_ID,ORG_NAME,PARENT_ORG_ID) values (222,'school-1',111);
Insert into ORG (ORG_ID,ORG_NAME,PARENT_ORG_ID) values (333,'school-2',111);
Insert into ORG (ORG_ID,ORG_NAME,PARENT_ORG_ID) values (444,'school-3',999);

查询:

select 
o1.org_id as orgId,
o1.org_name as orgName,
sum(nvl(quantity,0)) as totalLicense,
sum(case when END_DATE > systimestamp then quantity  else 0 end) as totalActiveLicense,
sum(case when END_DATE < systimestamp then quantity  else 0 end) as totalExpiredLicense,
sum(case when END_DATE > systimestamp-15 and END_DATE < systimestamp then quantity  else 0 end) as expiredInLast15Days,
sum(case when END_DATE > systimestamp-30 and END_DATE < systimestamp then quantity  else 0 end) as expiredInLast30Days,
sum(case when END_DATE > systimestamp-60 and END_DATE < systimestamp then quantity  else 0 end) as expiredInLast60Days,
sum(case when END_DATE < systimestamp+15 and END_DATE > systimestamp then quantity  else 0 end) as expiringInNext15Days,
sum(case when END_DATE < systimestamp+30 and END_DATE > systimestamp then quantity  else 0 end) as expiringInNext30Days,
sum(case when END_DATE < systimestamp+60 and END_DATE > systimestamp then quantity  else 0 end) as expiringInNext60Days
from org o1 left outer join (
select l.* from org o left outer join license l on o.org_id = l.org_id
where o.parent_org_id=111 or o.org_id=111
AND l.PRODUCT ='GOOGLE') license_info on o1.ORG_ID = license_info.org_id
where o1.parent_org_id=111 or o1.org_id=111
group by o1.org_id, o1.org_name;

查询应该让我返回父/子组织和他们每个人的许可证计数。

尽量避免多选。

下面的表结构和预期输出。

许可证表 1

组织表 2

输出

对此的任何帮助将不胜感激!谢谢!

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    您可以从父级开始。
    然后将许可证链接到父级和父级的子级。

    SELECT 
    org1.org_id AS orgId,
    org1.org_name AS orgName,
    lic.product,
    COALESCE(SUM(lic.quantity), 0) AS totalLicense,
    SUM(CASE WHEN lic.END_DATE > systimestamp THEN lic.quantity ELSE 0 END) AS totalActiveLicense,
    SUM(CASE WHEN lic.END_DATE < systimestamp THEN lic.quantity ELSE 0 END) AS totalExpiredLicense,
    SUM(CASE WHEN lic.END_DATE > systimestamp-15 AND lic.END_DATE < systimestamp THEN lic.quantity ELSE 0 END) AS expiredInLast15Days,
    SUM(CASE WHEN lic.END_DATE > systimestamp-30 AND lic.END_DATE < systimestamp THEN lic.quantity ELSE 0 END) AS expiredInLast30Days,
    SUM(CASE WHEN lic.END_DATE > systimestamp-60 AND lic.END_DATE < systimestamp THEN lic.quantity ELSE 0 END) AS expiredInLast60Days,
    SUM(CASE WHEN lic.END_DATE > systimestamp AND lic.END_DATE < systimestamp+15 THEN lic.quantity ELSE 0 END) AS expiringInNext15Days,
    SUM(CASE WHEN lic.END_DATE > systimestamp AND lic.END_DATE < systimestamp+30 THEN lic.quantity ELSE 0 END) AS expiringInNext30Days,
    SUM(CASE WHEN lic.END_DATE > systimestamp AND lic.END_DATE < systimestamp+60 THEN lic.quantity ELSE 0 END) AS expiringInNext60Days
    FROM org org1 
    JOIN org org2 ON (org2.org_id = org1.org_id OR org2.parent_org_id = org1.org_id)
    LEFT JOIN license lic 
      ON lic.org_id = org2.org_id 
     AND lic.product IN ('GOOGLE')
    WHERE org1.org_name = 'district-1'
    GROUP BY org1.org_id, org1.org_name, lic.product
    

    【讨论】:

    • 非常感谢您的回复@LukStorms 当我使用您的查询时,它会为我提供所有产品的一切。如果我通过 where 条件来获取特定产品。我只为那些包含该产品的组织获得结果。我想获得组织(父母和孩子),无论这些组织是否可以使用该产品。
    • @Naveen 啊,我认为这就是您在 WHERE 子句中为左连接表添加条件时得到的效果。这将过滤掉不匹配的,从而具有与 INNER JOIN 相同的效果。您可以通过将条件放入 LEFT JOIN 中来解决此问题:LEFT JOIN license lic ON (lic.org_id = org2.org_id AND lic.product = 'GOOGLE')
    • 清楚地理解@LukStorms。如果您愿意,可以使用此条件更新答案。
    • @Naveen 但如果您想要每个孩子的计数,那么您还应该将 org2.org_id, org2.org_name 放在 GROUP BY 和 SELECT 中
    猜你喜欢
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 2020-04-17
    • 2016-09-19
    相关资源
    最近更新 更多