【database】oracle關聯查詢主表對應的特定一行從表結果集


主表:

image

從表:

image

結果集: 查詢從表中年齡最大的一行數據,如果存在年齡相等的則為了保證唯一取id(主鍵)最大的一行。

image

一、利用sql子查詢嵌套
-- --------------------------------
-- 利用sql子查詢嵌套
-- --------------------------------
-- step 1. 子查詢:找到每組最大的子類年齡
select parent_id,max(child_age) from child group by parent_id;

-- step 2. 找到符合的行 (很可能出現重復)
select cc.* from child cc
  INNER JOIN (select parent_id,max(child_age) child_age from child group by parent_id) tmp
  on tmp.parent_id = cc.parent_id and tmp.child_age = cc.child_age
  order by cc.parent_id,cc.child_id;

-- step 3. 為了解決重復需要再加一層,取唯一標識id最大/最小的一行
select max(cc.child_id) from child cc
  INNER JOIN (select parent_id,max(child_age) child_age from child group by parent_id) tmp
  on tmp.parent_id = cc.parent_id and tmp.child_age = cc.child_age
  group by cc.parent_id,cc.child_age

-- step 4. 在3中就找到了符合條件行的id
select * from parent pa
  LEFT JOIN (SELECT cc.* from child cc
  INNER JOIN (select max(cc.child_id) child_id from child cc
  INNER JOIN (select parent_id,max(child_age) child_age from child group by parent_id) tmp 
  on tmp.parent_id = cc.parent_id and tmp.child_age = cc.child_age
  group by cc.parent_id,cc.child_age) tmp on TMP.child_id = cc.child_id
  ) tmp on tmp.parent_id = pa.parent_id
 where 1=1 ORDER BY pa.parent_id;
二、利用oracle自帶的分析函數
-- --------------------------------
-- 利用oracle分析函數
-- --------------------------------
-- step-1:找到子類符合的id, DISTINCT去重
select DISTINCT first_value(cc.child_id)
    over(partition by cc.parent_id order by cc.parent_id,cc.child_age desc,cc.child_id desc) child_id
  from child cc;
-- step-2: 符合的子類結果集
SELECT * from child cc where cc.child_id in(
  select DISTINCT first_value(cc.child_id)
    over(partition by cc.parent_id order by cc.parent_id,cc.child_age desc,cc.child_id desc) child_id
  from child cc
);

SELECT * from child cc where EXISTS ( select 1 from (
  select DISTINCT first_value(cc.child_id)
    over(partition by cc.parent_id order by cc.parent_id,cc.child_age desc,cc.child_id desc) child_id
  from child cc) tmp where tmp.child_id = cc.child_id
);

-- step-3: 最終結果集
select * from parent pa
  LEFT JOIN child cc on cc.parent_id = pa.parent_id
  and cc.child_id in(
    select DISTINCT first_value(cc.child_id)over(partition by cc.parent_id order by cc.parent_id,cc.child_age desc,cc.child_id desc)
  from child cc)
where 1=1 ORDER BY pa.parent_id
三、分析區別

sql嵌套當然要更通用點,而且看執行計划,它的效率、消耗都要比oracle少很多;

oracle分析函數感覺還是子查詢嵌套了一層,而且效率、消耗都比較高。

(才知道oracle的執行計划,完全不懂。只是看着sql嵌套查詢的執行計划高效很多)
C)6_@)R@9B)`EM9J]}87GY3

四、測試數據
-- -----------------------------
-- PARENT 父表
-- -----------------------------
CREATE TABLE "PARENT" (
"PARENT_ID" NUMBER NOT NULL ,
"PARENT_NAME" VARCHAR2(255 BYTE) NOT NULL
)
LOGGING NOCOMPRESS NOCACHE;
-- Records of PARENT
INSERT INTO "PARENT" VALUES ('1', '周父');
INSERT INTO "PARENT" VALUES ('2', '吳父');
INSERT INTO "PARENT" VALUES ('3', '鄭父');
INSERT INTO "PARENT" VALUES ('4', '王父');
INSERT INTO "PARENT" VALUES ('5', '趙父');
-- Checks structure for table PARENT
ALTER TABLE "PARENT" ADD CHECK ("PARENT_ID" IS NOT NULL);
ALTER TABLE "PARENT" ADD CHECK ("PARENT_NAME" IS NOT NULL);


-- -----------------------------
-- PARENT 子表
-- -----------------------------
CREATE TABLE "CHILD" (
"CHILD_ID" NUMBER NOT NULL ,
"CHILD_NAME" VARCHAR2(255 BYTE) NOT NULL ,
"CHILD_AGE" NUMBER NOT NULL ,
"PARENT_ID" VARCHAR2(255 BYTE) NOT NULL
)
LOGGING NOCOMPRESS NOCACHE;

-- ----------------------------
-- Records of CHILD
-- ----------------------------
INSERT INTO "CHILD" VALUES ('1', '周一', '6', '1');
INSERT INTO "CHILD" VALUES ('2', '周二', '8', '1');
INSERT INTO "CHILD" VALUES ('3', '周三', '7', '1');

INSERT INTO "CHILD" VALUES ('4', '吳一', '5', '2');
INSERT INTO "CHILD" VALUES ('5', '吳二', '3', '2');
INSERT INTO "CHILD" VALUES ('6', '吳三', '5', '2');
INSERT INTO "CHILD" VALUES ('7', '吳四', '2', '2');

INSERT INTO "CHILD" VALUES ('8', '鄭一', '8', '3');
INSERT INTO "CHILD" VALUES ('9', '鄭二', '4', '3');

INSERT INTO "CHILD" VALUES ('10', '王一', '18', '4');

-- Checks structure for table CHILD
ALTER TABLE "CHILD" ADD CHECK ("CHILD_ID" IS NOT NULL);
ALTER TABLE "CHILD" ADD CHECK ("CHILD_NAME" IS NOT NULL);
ALTER TABLE "CHILD" ADD CHECK ("CHILD_AGE" IS NOT NULL);
ALTER TABLE "CHILD" ADD CHECK ("PARENT_ID" IS NOT NULL);
測試表結構和數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM