SQL語句整理一

文章目錄

Postgre/Gauss

字符串拼接:
函數:concat('201911','01')
結果:2011101
數據類型轉換:
函數:cast(month_id as timestamp)
注意:當month_id值爲2011101時纔可以轉換爲timestamp成功,即轉換後值爲2019-11-01 00:00:00,如果month_id值爲20111時則轉換失敗
錯誤代碼:[0][SQLErrorCode : 3295]ERROR: date/time field value out of range: "201911"
  Hint: Perhaps you need a different "datestyle" setting.
當數字類型小於1時轉換爲字符類型後小數點前面的0不顯示:

目前我也沒有找到什麼好的方法,只能用case when判斷然後再進行拼接了

    case 
        when left(cast(cast(q.jdyysr as numeric(14,4)) as text),1)='.' then concat('0',cast(cast(q.jdyysr as numeric(14,4)) as text))
        else cast(cast(q.jdyysr as numeric(14,4)) as text)
        end jdyysr
coalesce函數:
select coalesce(success_cnt, 1) from tableA;
解釋:當success_cnt 爲null值的時候,將返回1,否則將返回success_cnt的真實值。
備註:nvl和ifnull函數也有這個效果,但是經我測試只有coalesce函數在Postgre、SQLserver、mysql中都適用,nvl只在Postgre中可以使用,而ifnull只可以在mysql中使用
隨機數random()函數:
--隨機字母 
select chr(int4(random()*26)+65);

--隨機4位字母
select repeat(chr(int4(random()*26)+65),4);

--隨機數字 十位不超過6的兩位數
select (random()*(6^2))::integer;

--三位數
select (random()*(10^3))::integer;
日期字段截取:
to_char(jsrq,'yyyy')='2019'要比left(jsrq,4)='2019'速度快將近一倍
select count(1) from tpcds.gr_yljf_yzh where left(jsrq,4)='2019';  用時1 mins, 41 sec
select count(1) from tpcds.gr_yljf_yzh where to_char(jsrq,'yyyy')='2019';  用時50 sec
注:表中有107675358條數據,jsrq(結算日期)字段數據格式爲“2019-11-01 00:00:00”
將字符串類型的數據“20200308191233”轉換成時間格式並精確到秒:
select to_date('20200308191233');
結果:2020-03-08 19:12:33
注意:當有想把某一個字符類型字段轉換成時間格式時發現該字段有爲null的數據該如何辦呢,直接轉的話會報錯the format is not correct!
解決:
select 
case 
	when "合同結束日期" is null then to_date('')
	else to_date(concat("合同結束日期",'000000'))
	end htjsrq
from 
tpcds.hehe;
將字符串類型的數據“20200308191233”轉換成時間戳格式:
SELECT cast(EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2016-05-25 14:30:50.352')*1000 as character varying(14));
運行結果:1464157850352
SELECT cast(EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2016-05-25 14:30:50')*1000 as character varying(14));
運行結果(該結果和用java轉換的結果一致):1464157850000
SELECT cast(EXTRACT(EPOCH FROM TIMESTAMP WITHOUT TIME ZONE '2016-05-25 14:30:50.352')*1000 as character varying(14));
運行結果:1464186650352
可以在該頁面校驗一下:https://tool.lu/timestamp/
業務語句:select cast(EXTRACT(epoch from cast(to_date(sqsj) as TIMESTAMP WITH TIME ZONE))*1000 as character varying(14)) from hehe.shbxhj_jcsj;
備註:sqsj字段的值格式爲“20200309105222”
字符串截取函數:
select substr('2019-11-02',6,2);
select substring('2019-11-02',6,2);
備註:運行結果都爲11,其中substr函數在gauss中可用,SQLserver中不可用
分割函數:
select split_part('8a59-e88177-ad5e70' ,'-', 3);
如果分割符數量不一樣怎麼辦,這裏就要計算分割符的數量了:
select split_part('8a59-e88177-ad5e70' ,'-', length(replace('8a59-e88177-ad5e70','-','--')) - length('8a59-e88177-ad5e70') + 1);
運行結果:ad5e70
replace函數:
問題:select '1294.00'/1000;
報錯:ERROR: invalid input syntax for integer: "1294.00"
解決:select REPLACE('1294.00','.00','')/1000;
四捨五入、向上取整、向下取整:

round() 函數是四捨五入用,第一個參數是我們要被操作的數據,第二個參數是設置我們四捨五入之後小數點後顯示幾位。
如:round(12.555,2) 結果:12.56

向上取整:select ceiling(45.88); 結果:46
向下取整:select floor(45.99); 結果:45

取整取餘:
取整:trunc(176/12)
結果:14

取餘:mod(176,12)
結果:8
前10行:
SELECT * FROM shbxhjzt.shbxhj_jcsj order by dwdm limit 10;
或者:
SELECT * FROM shbxhjzt.shbxhj_jcsj order by dwdm fetch first 10 rows only;
備註:在SQLserver中只能用top,上面兩種都不支持,同樣gauss也不支持top用法
select top 10 * from [lf_jybtjcpg].[dbo].[code_hangyexingzhi];
注意:最好加上order by,要不每次結果不一樣

補充:

1、SQL server的語法:
SELECT TOP number|percent column_name(s) FROM table_name;
例子:從表persons中選取前2行的數據;
SELECT TOP 2 * FROM persons;
從表persons中去前50%的 數據:
SELECT TOP 50 percent * from persons;

2、MySQL的語法:
SELECT column(s) FROM table_name LIMIT number;
例子:查看前5行數據:
SELECT * FROM persons LIMIT 5;

3、Oracle的語法:
SELECT * FROM table_name  where ROWNUM<=number;
例子:查看前5行的數據:
SELECT * FROM persons where ROWNUM <=5;
實現分頁功能:
select
    *
from 
    (     
        select          
            row_number() over(order by ID asc) as rownumber,*     
        from       
            shbxhjzt_tmp.shbxhj_sqhjdwxx     
        where       
            sqsj>='2020-03-01' and sqsj<='2020-03-31' 
    ) temp_row 
where      
    rownumber>(4-1)*9 fetch first 9 rows only;
備註:修改where後面的值即可達到分頁的功能,如第一頁展現9條數據爲rownumber>(1-1)*9,第二頁爲rownumber>(2-1)*9
not exists用法:
select 
    distinct dwdm
from 
    shbxhjzt.shbxhj_jcsj a
where 
    not exists (select 1 from  shbxhjzt_tmp.shbxhj_jcsj_eight b where a.dwdm = b.dwdm)
    and not exists (select 1 from shbxhjzt_tmp.shbxhj_jcsj_eighteen b where a.dwdm = b.dwdm);

select grid from tpcds.gr_xx_201912 a where exists (select sfzhm from mdl_ddpt_tmp.t_ryhx_zrrpj b where a.bzhm=b.sfzhm)
like用法:
select * from lsxgwbtzt.lsxgwbt_hmcryxx where sfzhm like '%X';
select * from lsxgwbtzt.lsxgwbt_hmcryxx where sfzhm not like '%X';
正則表達式:

說明:在postgresql中使用正則表達式時需要使用關鍵字“~”,以表示該關鍵字之前的內容需匹配之後的正則表達式,若匹配規則不需要區分大小寫,可以使用組合關鍵字“~*”;
相反,若需要查詢不匹配這則表達式的記錄,只需在該關鍵字前加否定關鍵字“!”即可。若正則表達式包含轉義字符,則需在表達式前加關鍵字“E”。

匹配email地址以A-H開頭的記錄:
select * from user where email ~ '^[A-H]';

過濾sfzhm字段不是身份證格式的數據:
select * from lsxgwbtzt.lsxgwbt_hmcryxx where sfzhm !~ '^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$';
轉義字符:

在PostgreSQL 9之前的版本中,可以直接使用反斜槓\進行轉義;比如:\b表示退格, \n表示換行, \t表示水平製表符,\r標示回車,\f表示換頁。除此之外還支持\digits\xhexdigits,分別表示轉義八進制和十六進制數據。

但是在PostgreSQL 9之後的版本,反斜槓已經變成了普通字符;如果想要使用反斜槓來轉義字符,就必須在需要轉義的字符串前面加上E(E就是Escape),如下:select E'張\t小明';

對單引號的兩種轉義方式:
在SQL標準中字符串是用單引號括起來的,而在PostgreSQL中遵守了該標準,雙引號則是用來表示變量的,如果在字符串中需要使用到單引號,就需要對其進行轉義。
方式一:使用E和反斜槓進行轉義select E'\'233';
方式二:直接用一個單引號來轉義單引號select '''233';

這兩種方式都能得到'233的結果而不會報錯,第二種方式比較簡單,也可以通過修改standard_conforming_strings參數的值來讓反斜槓從普通字符變回轉義字符:

show standard_conforming_strings;
SET standard_conforming_strings = on;
SET standard_conforming_strings = off;

當該參數的值爲off時就可以直接使用反斜槓作爲轉義字符裏,如下:select '\'233';
將會得到'233的結果而不會報錯。
來自:https://www.cnblogs.com/yulinlewis/p/9471721.html

注意:在實踐中遇到這麼個神奇的問題,在gsql裏執行這兩條語句都沒問題,但是在datastudio或者代碼中運行則會一條失敗一條成功。

失敗:
insert into tpcds.hehe(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31) VALUES
('123456','123456','123456','null','123456','123456','1','123456','01','40','1','123456','9','null','0','null','null','null','null','1','小城村\','123456','123456','null','0','null','13521390418','null','null','1','20');
成功:
insert into tpcds.hehe(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30) VALUES
('123456','123456','null','123456','123456','1','123456','01','40','1','123456','9','null','0','null','null','null','null','1','小城村\','123456','123456','null','0','null','13521390418','null','null','1');
失敗:
insert into tpcds.hehe(t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31) VALUES
(E'小城村\','123456','123456','null','0','null','13521390418','null','null','1','20');

整了半天咋也不知道啥原因,後來改變了思路,可以成功了,就是把反斜槓替換成反斜槓的Unicode碼插入則不會報錯了。即

insert into tpcds.hehe(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31) VALUES
('123456','123456','123456','null','123456','123456','1','123456','01','40','1','123456','9','null','0','null','null','null','null','1',E'小城村\u005c','123456','123456','null','0','null','13521390418','null','null','1','20');

提供兩個轉碼工具的連接:http://www.bejson.com/ 和 https://www.sojson.com/ascii.html(讓這個網站搞蒙了,在裏面輸入“\”,然後點擊字符轉換ASCII會生成結果“\u005c”,但前一個網站輸入“\u005c”再點擊“unicode轉中文”生成結果爲“\”,那麼\u005c到底是Unicode碼還是ASCII碼呢?有知道的網友可以留下言)

注意:轉換成Unicode碼插的時候目前測出有兩個是無法插入的,一個是\ufeff,另一個是\u0000,但是\u0001就可以。
在這裏插入圖片描述

日期加減:
postgres=# select sysdate;
       sysdate       
---------------------
 2020-02-12 14:03:25
(1 row)
相加:
postgres=# select sysdate + '2 month';
      ?column?       
---------------------
 2020-04-12 14:03:44
(1 row)
相減:
postgres=# select concat(to_char(sysdate + '-2 month','yyyymm'),'01');
  concat  
----------
 20191201
(1 row)
bbyf字段格式爲“2019-11-01 00:00:00”,csrq(出生日期)字段格式也一樣,計算年齡:
cast((date_part('year',age(sysdate,csrq))*12+date_part('month',age(sysdate,csrq)))/12 as int)  nlid
查詢某個日期之前的數據(包括這個日期):
select grid,csrq from sdp_jcsj.t_gaj_jc_hujirenkouxinxi_tmp where age(csrq,'1981-02-03')<=0;
使用case when查如果兩列不一致則賦個值的需求:
select case when sbkh=jydjh then '12472904100S' else '112' end hehe from sdp_jsc.t_ywdt_sbkjsjk; 
而不能寫成(報錯,語法不對):select case sbkh when sbkh=jydjh then '12472904100S' else '112' end hehe from sdp_jsc.t_ywdt_sbkjsjk;
對的語法:select case sbkh when '12472904100S' then '12472904100S' else '112' end hehe from sdp_jsc.t_ywdt_sbkjsjk;
把a表的數據插入到b表時id是以在b表最大id的基礎上實現自增:
INSERT INTO gc_shiyefeirenyuan
       (id
       ,tjrq
       ,dwid
       ,sbqncszrs
       ,btje
       ,sqxzqhdm
       ,rdqylx)
SELECT  row_number() over(order by bbny) + t2.sk_max,bbny
       ,dwid
       ,sbqncszrs
       ,btje
       ,sqxzqhdm
       ,rdqylx
FROM y_shiyebaoxianfeiyongkuanjihua
cross join (select coalesce(max(gc_shiyefeirenyuan.id),0) sk_max from gc_shiyefeirenyuan) t2
where bbny='201906' and if(btje is null,0,btje)>0;
把查詢的結果插入另一張表的兩張方式:
(1)select * into hehe from haha;
(2)create table hehe as select * from haha;
update和select結合使用:
UPDATE table1 t1
SET column1 = t2.columnname1,
    column2 = t2.columnname2
 FROM (select columnname1,columnname2 from table2) t2
 WHERE t1.column3 = t2.column3
 AND t1.column = '111';
用戶解鎖:
ALTER USER  jack  ACCOUNT UNLOCK;
刪除用戶:
DROP USER jack CASCADE;
注:如果用該用戶執行了插入數據等則上述命令將不能執行成功,即不能刪除有數據的用戶(我當時是用Jack用戶執行了GaussDBTest.jar創建customer_t1並插入了數據,將這個表刪除之後就可以將該用戶刪除了)
postgres=# drop user jack;
ERROR:  role "jack" cannot be dropped because some objects depend on it
DETAIL:  1 object in database hwbase
創建用戶並賦予密碼:
CREATE USER hui PASSWORD 'hehe';
創建數據庫並使某用戶擁有:
create database hui owner hui;或者CREATE DATABASE hui WITH OWNER=hui;
GRANT CONNECT ON DATABASE hui TO hui;
修改用戶密碼:
alter user jack identified by "heheda";
注:密碼不能複用
賦予用戶所有權限:
GRANT ALL PRIVILEGES TO hui;
查詢都有什麼用戶:
SELECT * FROM PG_TOTAL_USER_RESOURCE_INFO;
查詢都有什麼數據庫、庫下有什麼模式、模式下有什麼表、表裏什麼字段:

查詢都有什麼庫(相當與mysql的show databases):select datname from pg_database;
查詢庫下有什麼模式:SELECT table_catalog,table_schema FROM information_schema.columns where table_catalog='db_perfect' group by table_catalog,table_schema;
查詢模式下有什麼表(相當於mysql的show tables):SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';或者select tablename from pg_tables where schemaname='public';
查詢表裏有什麼字段(相當與mysql的describe table_name):SELECT column_name FROM information_schema.columns WHERE table_name ='code_jntspxgz' and table_catalog='db_perfect' and table_schema='sdp_jcsj';

創建schema:
CREATE SCHEMA wuxian_shiye;
判斷某個schema是否存在:
SELECT EXISTS(SELECT 1 FROM information_schema.schemata WHERE schema_name = 'sjhj');
SELECT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = 'sjhj');

兩種方式都可以,第二個更有效率一些。
創建主鍵並設置自動遞增的三種方法:

來自:http://francs3.blog.163.com/blog/static/40576727201111715035318/
方法一:

create table test_a 
(
  id serial,
  name character varying(128),
  constraint pk_test_a_id primary key( id)
); 

方法二:

create table test_b
(
  id serial PRIMARY KEY,
  name character varying(128)
); 

方法三:

create table test_c 
(
  id integer PRIMARY KEY,
  name character varying(128)
);  

CREATE SEQUENCE test_c_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;
    
alter table test_c alter column id set default nextval('test_c_id_seq');

很明顯從上面可以看出,方法一和方法二隻是寫法不同,實質上主鍵都通過使用 serial 類型來實現的,使用serial類型,PG會自動創建一個序列給主鍵用,當插入表數據時如果不指定ID,則ID會默認使用序列的NEXT值。
方法三是先創建一張表,再創建一個序列,然後將表主鍵ID的默認值設置成這個序列的NEXT值。這種寫法似乎更符合人們的思維習慣,也便於管理,如果系統遇到sequence 性能問題時,便於調整 sequence 屬性;
三個表表結構一模一樣, 三種方法如果要尋找差別,可能僅有以下一點,當 drop 表時,方法一和方法二會自動地將序列也 drop 掉, 而方法三不會。

創建臨時表:
create TEMPORARY table temp1 as select * from tpcds.事_單位信息;
查詢臨時表屬性:
select * from pg_catalog."pg_class" where relname = 'temp1';
查詢庫下的所有外表:
select oid,* from pg_class where oid in (select ftrelid from pg_foreign_table);
查看錶大小:
select pg_size_pretty(pg_table_size('tpcds."事_單位信息"'));
查看指定庫大小:
select pg_size_pretty(pg_database_size('postgres'));
查看所有數據庫大小:
select pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size from pg_database;
查詢結果:
template1	88 MB
hwbase	621 GB
wuxian	95 GB
template0	88 MB
postgres	102 MB
查看待刪除涉及query_id、pid:
Select query,query_id,pid from pg_stat_activity where query like '%faren_jichushuju_20191115_ext%';
select pg_cancel_backend(140585035888384);   --殺死進程
給列添加備註:
comment on column sdp_jsc_test.cbfbqk.rq is '創建日期';
給表增加列:
alter table tmp1 add xzqmc varchar(50);
索引:
--查詢索引
select * from pg_indexes where tablename='t_source_dwxx';

--創建索引
create index t_source_dwxx_index on ycxjycyfwbt.t_source_dwxx(dwid);

--刪除索引
drop index ycxjycyfwbt.t_source_dwxx_index;
查看索引有沒有生效:
explain analyze select * from heheda.haha where sfzhm='110';
或者
explain performance select * from heheda.haha where sfzhm='110';

注:
EXPLAIN PERFORMANCE statement:生成執行計劃,進行執行,並顯示執行期間的全部信息。
EXPLAIN ANALYZE statement:生成執行計劃,進行執行,並顯示執行的概要信息。顯示中加入了實際的運行時間統計,包括在每個規劃節點內部花掉的總時間(以毫秒計)和它實際返回的行數。

注意:執行這個命令可能出不來index,得先執行該命令set enable_fast_query_shipping=off;
每加該條命令之前執行explain analyze命令:
在這裏插入圖片描述
之後:
在這裏插入圖片描述

表空間:
--創建表空間
CREATE TABLESPACE huihui1 RELATIVE LOCATION 'tablespace1/huihui1';

--查詢都有什麼表空間
SELECT * FROM pg_tablespace;

--刪除表空間
DROP TABLESPACE huihui1;
\set用法:
postgres=# \set monthid1 20191001
或者:
postgres=# \set monthid1 '20191001'
postgres=# select :'monthid1';
 ?column? 
----------
 20191001
(1 row)
postgres=# select :monthid1;
 ?column? 
----------
 20191001
(1 row)

postgres=# \set monthid1 'select 20191001'
或者:
postgres=# \set monthid1 'select '20191001''
postgres=# :monthid1;
 ?column? 
----------
 20191001
(1 row)
postgres=# (:monthid1);
 ?column? 
----------
 20191001
(1 row)

postgres=# create TEMPORARY table month_table as select concat(to_char(sysdate + '-2 month','yyyymm'),'01') rq;
NOTICE:  The 'DISTRIBUTE BY' clause is not specified. Using 'rq' as the distribution column by default.
HINT:  Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
INSERT 0 1
postgres=# \set monthid1 'select rq from month_table'
postgres=# select rq from month_table where rq=(:monthid1);
    rq    
----------
 20191201
(1 row)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章