- 已知一個字符類型的日期:2022-01-20,請用SQL顯示出此日期對應的下個月的月份,結果要求為Number類型(202201)。
參考答案
sql
SELECT to_date('2022-01-20', 'yyyy-mm-dd') a1,add_months(to_date('2022-01-20', 'yyyy-mm-dd'), 1) a2,to_char(add_months(to_date('2022-01-20', 'yyyy-mm-dd'), 1), 'yyyymm') a3,to_number(to_char(add_months(to_date('2022-01-20', 'yyyy-mm-dd'), 1),'yyyymm')) a4,CAST(to_char(add_months(to_date('2022-01-20', 'yyyy-mm-dd'), 1),'yyyymm') AS NUMBER) a5FROM dual;
- 一個來源表TEMP2_F,數據如下,請用SQL刪除表中的重復記錄。
ID | CODE |
1 | D1 |
2 | D2 |
1 | D1 |
3 | D2 |
2 | D3 |
2 | D2 |
3 | D1 |
參考答案
sql
CREATE TABLE temp2_f (ID NUMBER(2),CODE VARCHAR2(3));SELECT * FROM temp2_f;
解:
--用rowid找出重復的數據
--找出每個重復數據里最小的那個(在每個重復只有兩個的情況才下)
--那如果有個重復有三個怎么辦?--groupby所有能輸出的值
--用delete表語句刪除重復的數據(not in…………)
---刪除表數據:DELETE FROM 表名 WHERE 條件;DELETE FROM temp2_fWHERE ROWID NOT IN(SELECT MIN(ROWID) FROM temp2_f f GROUP BY f.id, f.code);
COMMIT;
3.來源表TEMP3_F,字段類型及數據如下:
字段類型 | DATE | VARCHAR2(20) | VARCHAR2(20) | NUMBER |
字段名 | INPUT_DATE | C1 | C2 | AMT |
2021/10/03 | A | P1 | 30 | |
2021/11/04 | B | P1 | 20 | |
2021/10/05 | A | P2 | 50 | |
2021/12/04 | B | P1 | 20 |
根據以上數據,請用SQL按以下要求輸出結果,要求在同一個PERIOD_ID中C1 不能重復。
字段類型 | VARCHAR2(20) | NUMBER | NUMBER(38,10) | NUMBER(38,10) |
字段名 | C1 | PERIOD_ID | AMT1 | AMT2 |
規則說明 | C1 | 根據字段INPUT_DATE轉換,格式為YYYYMM | 根據C1+PERIOD_ID分組的AMT匯總 | 全表AMT的總計 |
參考答案
sql
--建表:CREATE TABLE temp3_f (input_date DATE,c1 VARCHAR2(20),c2 VARCHAR2(20),amt NUMBER);SELECT * FROM temp3_f;根據以上數據,請用SQL按以下要求輸出結果,要求在同一個PERIOD_ID中C1 不能重復。--方法一
SELECT DISTINCT c1,to_number(to_char(input_date, 'yyyymm')) PERIOD_ID,SUM(amt) OVER(PARTITION BY to_number(to_char(input_date, 'yyyymm')), c1) AMT1,SUM(amt) OVER() AMT2FROM temp3_f;--方法二
SELECT c1, PERIOD_ID, MAX(amt1) amt1, MIN(amt2) amt2FROM (SELECT c1,to_number(to_char(input_date, 'yyyymm')) PERIOD_ID,SUM(amt) OVER(PARTITION BY to_number(to_char(input_date, 'yyyymm')), c1) AMT1,SUM(amt) OVER() AMT2FROM temp3_f)GROUP BY c1, PERIOD_ID;
4.來源表?TEMP4_F,字段類型及數據如下:
字段類型 | NUMBER | VARCHAR2(20) | VARCHAR2(20) | NUMBER(38,10) |
字段名 | ID | TYPE | ACC_CODE | AMT |
1 | CR | 1001 | 50 | |
1 | DR | 1002 | 60 | |
2 | CR | 1003 | 80 | |
2 | DR | 9999 | 100 | |
3 | DR | 2005 | 110 | |
4 | CR | 1001 | 30 |
根據以上數據,請用SQL按以下要求輸出結果,要求DR的ACC_CODE不為9999。
字段類型 | NUMBER | VARCHAR2(20) | NUMBER(38,10) | VARCHAR2(20) | NUMBER(38,10) |
字段名 | ID | DR_ACC_CODE | DR_AMT | CR_ACC_CODE | CR_AMT |
規則說明 | ID | 源表TYPE為DR對應的ACC_CODE的值 | 源表TYPE為DR對應的AMT的值 | 源表TYPE為CR對應的ACC_CODEE的值 | 源表TYPE為CR對應的AMT的值 |
參考答案
sql
--建表
CREATE TABLE temp4_f (ID NUMBER,TYPE VARCHAR2(20),acc_code VARCHAR2(20),amt NUMBER(38,10));SELECT * FROM temp4_f;根據以上數據,請用SQL按以下要求輸出結果,要求DR的ACC_CODE不為9999。
--cr、dr 分別 行轉列--根本不用
--再full join--根本不用,而且我耶找不到關聯條件
--還要剔除dr acc_code=9999的數據SELECT id,SUM(CASEWHEN TYPE = 'DR' AND acc_code != 9999 THENACC_CODEEND) DR_ACC_CODE,SUM(CASEWHEN TYPE = 'DR' AND acc_code != 9999 THENAMTEND) DR_AMT,SUM(CASEWHEN TYPE = 'CR' THENACC_CODEEND) CR_ACC_CODE,SUM(CASEWHEN TYPE = 'CR' THENAMTEND) CR_AMTFROM temp4_f
---WHERE acc_code!=9999 ---錯 GROUP BY ID;
--行轉列有時候要groupby 有時候又不要groupby,這是為什么?與sum又什么關系?
5.用sql邏輯實現求中位數 提示:用排名函數
參考答案
sql
--理解中位數
--求emp表中sal的中位數
SELECT MEDIAN(sal) m_sal
FROM emp;--方法一:
SELECT AVG(t2.sal) 中位數FROM (SELECT CASEWHEN MOD(COUNT(1), 2) = 0 THENCOUNT(1) / 2ELSE(COUNT(1) + 1) / 2END lrn,CASEWHEN MOD(COUNT(1), 2) = 0 THENCOUNT(1) / 2 + 1ELSE(COUNT(1) + 1) / 2END rrnFROM emp) t1JOIN (SELECT sal, row_number() OVER(ORDER BY sal) rn FROM emp) t2ON t1.lrn = t2.rnOR t1.rrn = t2.rn;--方法二SELECT AVG(SAL) ZWSFROM (SELECT empno,SAL,ROW_NUMBER() OVER(ORDER BY SAL) R,COUNT(*) OVER() AFROM EMP) ZWHERE R BETWEEN FLOOR((1 + A) / 2) AND CEIL((1 + A) / 2);