Teradata SQL programming


Teradata的SQL設計和Oracle真不是一個水平, 一點美感的沒有.  
上個世紀它靠着MPP一招鮮吃變天, 居然做了十多年數據倉庫的老大,  時過境遷, 現在有不少SQL On Hadoop 產品已經出來了, 考慮到scale out的成本和能力, Teradata 數據倉庫優勢盪然全無. 將來必將會被SQL on Hadoop/Spark替代.

畢竟在Teradata上做了幾年, 也該寫點總結. 下面是我常用的一些編程知識

--字符串函數
    SELECT 'FirstName' || ' ' || 'LastName' as Full_Name;
    CHAR2HEXINT ('A')
    --would result in the value ‘0041’.
    LOWER()
    substr()
    TRIM()
    UPPER()
    CHARACTERS() 或 character_length() 得到字符串的長度
    SELECT position ('a' in 'Name')
    oracle version replace(), no way. write your code


---type() 可返回 字段的類型,
SELECT
    CAST(100.00 AS DECIMAL(15,2)) * CAST(100.00 AS DECIMAL(15,2)) AS C1
  , TYPE(C1)    
 

--獲取字段類型
select type('abc')


--get current date
select current_date
select current_time
select current_timestamp(0) --不帶毫秒
select current_timestamp --帶6位毫秒, 最高精度


--日期加減
select current_date+1 --得到明天
select add_months(current_timestamp,1)  --得到下一個月
select add_months(current_date ,1)-current_date --兩個日期相差多少天
select add_months(current_timestamp,1) -current_timestamp day(4) to second --兩個時間戳相減, 仍是時間戳


--使用INTERVAL進行時間日期的增減
Select current_date + interval '1' year
Select current_date - interval '1' year
Select current_date + interval '1' month
Select current_date + interval '1' day
Select current_timestamp + interval '1' hour
Select current_timestamp + interval '1' minute
Select current_timestamp + interval '1' second


--兩個 timestamp 相減, 結果仍是一個timestamp, 而日期相減, 結果為相差的天數
select cast (endtime as   timestamp(0)  format 'yyyy-mm-ddbhh:mi:ss') -
           cast (starttime as   timestamp(0)  format 'yyyy-mm-ddbhh:mi:ss') DAY(4) TO SECOND ,
        a. *  from      PETL.ETL_JOB_STATUS A
where 1=1
and jobstatus='Done';
The DAY(4) specifies four digits of precision, and allows for a maximum of 9999 days, or
approximately 27 years.


-- timestamp 相減, 前3個寫法, 要求時間跨度不能太大, 會溢出的
select ((current_timestamp + interval '1' hour )  -current_timestamp)  day(4)           --得到的差多少天
select ((current_timestamp + interval '1' hour )  -current_timestamp)  hour(4)          --得到的差多少小時
select ((current_timestamp + interval '25' hour ) -current_timestamp)  minute(4)        --得到的差多少分
select ((current_timestamp + interval '1' hour )  -current_timestamp)  day(4) to second --得到的是timestamp

 
--統計執行總時長
select txdate
,sum(extract(DAY from duration)) * 24.000
+sum(extract(HOUR from duration)) *1.000
+sum(extract(MINUTE from duration)) /60.000
+sum(extract(SECOND from duration)) /3600.000
   as duration_hours from
(
select  cast (endtime as   timestamp(0)  format 'yyyy-mm-ddbhh:mi:ss') -
        cast (starttime as   timestamp(0)  format 'yyyy-mm-ddbhh:mi:ss') day(4) TO SECOND  duration,
        txdate  from     PETL.ETL_JOB_STATUS A
where 1=1
and jobstatus='Done'
and A.txdate>=date'2012-06-01'
and A.txdate<date'2012-07-19'
)  xx
group by  xx.txdate
order by  xx.txdate
;





--從日期中提取年月日
select EXTRACT(YEAR  FROM  current_date)
    YEAR
    MONTH
    DAY
    HOUR
    MINUTE
    SECOND
    TIMEZONE_HOUR
    TIMEZONE_MINUTE
    
    
--幾個有用的查詢    
select user
select session
select role    
select * from sys_calendar.calendar


--字符轉日期
select date'2012-05-12'
select CAST('20120512' AS DATE FORMAT 'YYYYMMDD')   

--字符轉 timestamp
select cast ('20120512 231056'  as timestamp(0) FORMAT 'YYYYMMDDBHHMISS' )  

--日期 轉 字符串
--recommended usage, statement 1
SELECT CAST(cast(current_date AS FORMAT 'yyyymmdd') as varchar(8))
select current_date (format 'YYYYMMDD') (varchar(8))

--timestamp 轉 字符串
--recommended usage, statement 1
SELECT CAST(CAST(TIMESTAMP'2010-03-12 14:32:45' AS FORMAT 'yyyymmddbhh:mi:ssbt') AS varchar(20));
select current_timestamp (format 'YYYYMMDDBHHMISS') (varchar(15))
SELECT CAST(TIMESTAMP'2010-03-12 14:32:45' AS FORMAT 'yyyymmddbhh:mi:ssbt') (varchar(20));

--error when runing
select current_date (format 'YYYYMMDD') (varchar(8))||'abc'
--how to achieve
select CAST(cast(current_date AS FORMAT 'yyyymmdd') as varchar(8))||'abc'


--合並日期和時間 為 timestamp
SELECT CAST(CAST(CURRENT_DATE AS FORMAT 'YYYY-MM-DD') || ' ' || CAST(CAST(CURRENT_TIME AS FORMAT 'HH:MI:SS') AS CHAR(8)) AS TIMESTAMP(0));


--searched case 語句
case
    when AA=v1 then r1
    when AA=v2 then r2
    else null
end
--value case 語句
case AA
    when v1 then r1
    when v2 then r2
    else null
end

--case 變種 NULLIF
NULLIF returns NULL if its arguments are equal. Otherwise, it returns its first argument,
scalar_expression_1.
--case 變種 COALESCE
COALESCE returns NULL if all its arguments evaluate to null. Otherwise, it returns the value
of the first non-null argument in the scalar_expression list.
oracle:nvl(f1,f2...),teradata:coalesce(f1,f2...)


=====================================
 建表  
=====================================
--創建 MULTISET 表
 MULTISET:默認為 SET;
 NO LOG:默認為 LOG,LOG指示維護交易日志,NO LOG 的性能更好;
 
create MULTISET table t1
(f1 integer, f2 integer) PRIMARY INDEX ( f1 )  ;
;
 
--創建臨時表  
CREATE MULTISET TABLE PDATA.EQP_PERF_HIS_SS1_CUR_I AS PDATA.EQP_PERF_HIS
WITH NO DATA
PRIMARY index (fab_code)
;
 CREATE MULTISET TABLE PDATA.EQP_PERF_HIS_SS1_CUR_I AS (select * from PDATA.EQP_PERF_HIS)
 WITH NO DATA
 --WITH DATA
 PRIMARY index (fab_code)
 ;
 真正的臨時表 volatile , session 結束后自動drop, 也可以手動刪除
 CREATE VOLATILE MULTISET TABLE PDATA.EQP_PERF_HIS_SS1_CUR_I AS (select * from PDATA.EQP_PERF_HIS)
 WITH NO DATA
 --WITH DATA
 PRIMARY index (fab_code)
 
 還有一種 GLOBAL TEMPORARY  TABLE, 不常用.
 
 
 
大小寫敏感
--default, 大小寫不敏感
select f from (select 'a' f ) dual_a  where 1=1 and f = 'A'
select f from (select 'a' f ) dual_a  where 1=1 and f like '%A%'
--大小寫敏感的寫法
select f from (select 'a' f ) dual_a  where 1=1 and f(casespecific) like '%A%'



select * from scott.emp where ename(CASESPECIFIC) = 'FAN';--使用關鍵字CASESPECIFIC將區分大小寫
 
    
轉義 _ 字符, 下例是使用\取轉義_
select * from like_escape_test where some_text like '%\_%' escape '\';
    
top n 語句
  select top 10 * from table_a order by field_a;
 

UPDATE Specifying a Correlation Name for the Updated Table in the FROM Clause
需要說明的是, SET 子句中的目標字段不能加表名alias.
    UPDATE e
    FROM employee AS e, department AS d
    SET salary = salary * 1.05
    WHERE e.emp_no = d.emp_no
    AND d.name LIKE '%Support%'    
    
    
    
update join 語句
    UPDATE employee
    SET salary_amount=salary_amount * 1.10
    WHERE employee.dep_no = department.dep_no
    AND department.name LIKE '%Support%'
    ;  
 

Note: In an update, you can't use the ON clause,
so the join condition is specified in the WHERE clause.     

在SP中, 可以使用變量,  但在Macro中, 是不能使用變量. 聲明變量必須放在SP的開頭部分. 語法為:
DECLARE vcount INTEGER DEFAULT 0;
DECLARE temp1, par1 VARCHAR(40) DEFAULT NULL;

Teradata沒有 oracle的打印功能, 下面的語句並不能輸出
PRINT 'EmpNo:', vcount;


使用游標 cursor
FOR loopvar AS cur1 CURSOR FOR
SELECT employee_number, department_number FROM employee
DO
     PRINT 'EmpNo:', loopvar.employee_number;
END FOR;
上面的例子中示范了游標的規則:
1.聲明游標,需要使用 FOR 語句。
2.要賦予游標一個名字,例子中的名字為 cur1
3.要給循環賦一個名字 loopvar


定義SP
REPLACE PROCEDURE PDATA.SP_WAT_PARAMETERS()
BEGIN
END;

定義Macro
REPLACE  MACRO MARTVIEW_KPI.EIS_INDEX_RESULT_MACRO(SQL_Date VARCHAR(20))
AS
(
);


-- 動態執行sql語句
--===========================
SET Sql_text = 'DELETE FROM temp_Table' ;
CALL DBC.SYSEXECSQL(:Sql_text) ;    


=====================================
-- bteq 命令行工具
=====================================
bteq工具的調用方法是:
bteq <sql_file.btq >log.txt

下面是sql_file.btq文件的內容
.LOGON  ip/userid,pwd

drop table     SMCTA.SS1SDBSDB_TB_INFO_EQP4687                 ;
;
.IF ERRORCODE <> 0 THEN .GOTO QUITWITHERROR;


SELECT 1 ;

.IF ACTIVITYCOUNT = 0 THEN .GOTO QUITWITHNOERROR;
.GOTO QUITWITHNOERROR;


.LABEL QUITWITHERROR
.LOGOFF;
.QUIT 12;

.LABEL QUITWITHNOERROR
.LOGOFF;
.QUIT 0;

.LOGOFF
上面是sql_file.btq文件的內容



=====================================
-- jdbc訪問
=====================================
JDBC connection string:
url="jdbc:teradata://edwprd/TMODE=TERA,CHARSET=ASCII,CLIENT_CHARSET=cp936,DATABASE=TESTDB,lob_support=off"
edwprd為IP, 考慮到Teradata是多節點一體機, 最好是在hosts中,  定義一個域名解析規則, 這樣就有了多節點冗余的功能.

Hosts:
153.65.129.189                   edwprd  dbccop1
153.65.129.190                   edwprd  dbccop2
153.65.129.191                   edwprd  dbccop3
153.65.129.192                   edwprd  dbccop4


免責聲明!

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



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