I am having an issue on joining a table to a result in a substring in SQL.
Here is my statement:
SELECT a.MEASR_COMP_ID
, f.D1_USAGE_ID
, f.SCH_SELECTION_DT
, g.MEASR_COMP_ID
, g.MSRMT_VAL
, i.USAGE_ID
, SUBSTR(dbms_lob.substr(i.USG_DATA_AREA, 4000, 1)
,INSTR(dbms_lob.substr(i.USG_DATA_AREA, 4000, 1)
,'<startReading>') + LENGTH('<startReading>'), 8)
"Start Reading"
, SUBSTR(dbms_lob.substr(i.USG_DATA_AREA, 4000, 1)
, INSTR(dbms_lob.substr(i.USG_DATA_AREA, 4000, 1)
, '<endReading>') + LENGTH('<endReading>'), 8) as "End Reading"
FROM C1_USAGE I
, CISADM.D1_USAGE#CCBMDM f
, CISADM.D1_MSRMT#CCBMDM g
, CISADM.D1_USAGE_PERIOD_SQ#CCBMDM a
WHERE f.USG_EXT_ID = i.USAGE_ID AND
f.D1_USAGE_ID = a.D1_USAGE_ID AND
a.MEASR_COMP_ID = g.MEASR_COMP_ID AND
i.USAGE_ID = '119993413555' AND
SUBSTR(dbms_lob.substr(i.USG_DATA_AREA, 4000, 1)
,INSTR(dbms_lob.substr(i.USG_DATA_AREA, 4000
,1), '<endReading>') + LENGTH('<endReading>'), 8)
as "End Reading" = g.MSRMT.VAL
It should be fine except that you should remove the part as "End Reading" from your condition and also consider using proper ANSI style JOIN syntax rather this puzzled syntax
Related
What should I check why Oracle server takes more then 20 sec to return UNIQUE constraint violation error for specific data?
One of our processes is processing over 30000 data one day with multi process and some time gets UNIQUE constraint violation error in 1 sec
but it takes more then 20 sec to return UNIQUE constraint violation error for specific data.
Query is same as below. (Modified only table name)
MERGE
INTO TableA S
USING (
SELECT NVL(:sccm_cd , ' ') SCCM_CD
, NVL(:oder_dt , ' ') ODER_DT
, NVL(:mrkt_dstn_cd, ' ') MRKT_DSTN_CD
, NVL(:oder_no , ' ') ODER_NO
, NVL(:cncd_unpr , 0) CNCD_UNPR
, B.SLBY_FEE_GRD_CD
, B.ACCT_MNGR_EMPL_NO
, C.AO_FEE_GRD_CD
FROM DUAL A
, TableB B
, TableC C
WHERE 1 = 1
AND B.SCCM_CD = :sccm_cd
AND B.ACNO = :acno
AND C.SCCM_CD(+) = B.SCCM_CD
AND C.EMPL_NO(+) = B.ACCT_MNGR_EMPL_NO
) T
ON ( S.sccm_cd = T.sccm_cd
AND S.oder_dt = T.oder_dt
AND S.mrkt_dstn_cd = T.mrkt_dstn_cd
AND S.oder_no = T.oder_no
AND S.cncd_unpr = T.cncd_unpr
)
WHEN MATCHED THEN
UPDATE
SET S.cncd_qty = S.cncd_qty + NVL(:cncd_qty ,0)
, S.slby_fee = S.slby_fee + NVL(:slby_fee ,0)
, S.slby_fee_srtx = S.slby_fee_srtx + NVL(:slby_fee_srtx,0)
, S.idx_fee_amt = S.idx_fee_amt + NVL(:idx_fee_amt ,0)
, S.cltr_fee = S.cltr_fee + NVL(:cltr_fee ,0)
, S.trtx = S.trtx + NVL(:trtx ,0)
, S.otc_fee = S.otc_fee + NVL(:otc_fee ,0)
, S.wht_fee = S.wht_fee + NVL(:wht_fee ,0)
WHEN NOT MATCHED THEN
INSERT (
sccm_cd
, oder_dt
, mrkt_dstn_cd
, oder_no
, cncd_unpr
, acno
, item_cd
, slby_dstn_cd
, md_dstn_cd
, cncd_qty
, stlm_dt
, trtx_txtn_dstn_cd
, proc_cmpl_dstn_cd
, item_dstn_cd
, slby_fee_grd_cd
, slby_fee
, slby_fee_srtx
, idx_fee_amt
, cltr_fee
, trtx
, wht_fee
, otc_fee
, acct_mngr_empl_no
, ao_fee_grd_cd
)
VALUES
( T.sccm_cd
, T.oder_dt
, T.mrkt_dstn_cd
, T.oder_no
, T.cncd_unpr
, :acno
, :item_cd
, :slby_dstn_cd
, :md_dstn_cd
, NVL(:cncd_qty ,0)
, DECODE(:mrkt_dstn_cd, 'TN', T.oder_dt, :stlm_dt)
, :trtx_txtn_dstn_cd
, '0'
, :item_dstn_cd
, NVL(:slby_fee_grd_cd, T.SLBY_FEE_GRD_CD)
, NVL(:slby_fee ,0)
, NVL(:slby_fee_srtx ,0)
, NVL(:idx_fee_amt ,0)
, NVL(:cltr_fee ,0)
, NVL(:trtx ,0)
, NVL(:wht_fee , 0)
, NVL(:otc_fee , 0)
, T.acct_mngr_empl_no
, T.ao_fee_grd_cd
)
There could be multiple reasons for it. I will list here some of the possible causes for this behavior.
Concurrency issue
Your insert might be waiting for other operations, like other inserts or updated or deletions.
Network issues
It is possible that for some reason your network is overwhelmed with requests or, if the server is remote, this could be an internet speed issue as well.
Server load
The server might be overwhelmed with lots of jobs to do.
Slow query
It's also possible that the select you use in your insert command is very slow. It would make sense to test its speed. Also, it would make sense to test insert speed as well.
I am trying to output a date format within the below SQL
CASE
WHEN E.A_EXTTRNDTETME IS NOT NULL then LEFT(E.A_EXTTRNDTETME, 4)
+SUBSTRING(E.A_EXTTRNDTETME, 5, 2)+SUBSTRING(E.A_EXTTRNDTETME, 7, 2)
+'-'+SUBSTRING(E.A_EXTTRNDTETME, 9, 2)+':'+SUBSTRING(E.A_EXTTRNDTETME, 11, 2)
+':'+SUBSTRING(E.A_EXTTRNDTETME, 13,2)+'.'+SUBSTRING(E.A_EXTTRNDTETME, 15,3)
WHEN E.A_EXTTRNDTETME IS NULL then
(
SELECT TOP 1 A_EXTTRNDTETME FROM T_ATH_EXE
WHERE A_PAREXEID = E.A_EXEID ORDER BY A_ADDDTETME
)
ELSE ' text'
END as [TransactTime],
The second WHEN statement is returning 20180322141422883 but I would like this to be in the following format, like the values from the first branch:
20180322-14:14:22.883
But don't know how to do it inside the SELECT statement, please help.
You can put your entire query into a subquery, so you only have to apply formatting once. You can also use COALESCE, which is just a shorter way to write CASE WHEN IS NOT NULL THEN this ELSE that END. Finally, there are built in style options for formatting datetime values that avoid all that messy string manipulation (you can see all the options here).
SELECT *, TransactTime = COALESCE
(
CONVERT(char(8), dt, 112) + '-' + CONVERT(char(12), dt, 108),
' text'
)
FROM -- your larger query here
(
SELECT
dt = COALESCE
(
E.A_EXTTDNDTETME,
(
SELECT TOP (1) A_EXTTRNDTETME
FROM T_ATH_EXE
WHERE A_PAREXEID = E.A_EXEID
ORDER BY A_ADDDTETME
)
), -- other columns...
FROM -- table...
) AS sub;
I got it working by using the following:-
CASE
WHEN E.A_EXTTRNDTETME IS NULL then (SELECT top 1 LEFT(A_EXTTRNDTETME, 4)+SUBSTRING(A_EXTTRNDTETME, 5, 2)+SUBSTRING(A_EXTTRNDTETME, 7, 2)+'-'+SUBSTRING(A_EXTTRNDTETME, 9, 2)+':'+SUBSTRING(A_EXTTRNDTETME, 11, 2)+':'+SUBSTRING(A_EXTTRNDTETME, 13,2)+'.'+SUBSTRING(A_EXTTRNDTETME, 15,3) FROM T_ATH_EXE WHERE A_PAREXEID = E.A_EXEID ORDER BY E.A_ADDDTETME)
WHEN E.A_EXTTRNDTETME IS NOT NULL then LEFT(E.A_EXTTRNDTETME, 4)+SUBSTRING(E.A_EXTTRNDTETME, 5, 2)+SUBSTRING(E.A_EXTTRNDTETME, 7, 2)+'-'+SUBSTRING(E.A_EXTTRNDTETME, 9, 2)+':'+SUBSTRING(E.A_EXTTRNDTETME, 11, 2)+':'+SUBSTRING(E.A_EXTTRNDTETME, 13,2)+'.'+SUBSTRING(E.A_EXTTRNDTETME, 15,3)
ELSE ' text'
END as [TransactTime],
while doing an sql query, i have a field Gift_Number which give me the below data
Gift certificat (-) [2989153053216]
Sql Query :
SELECT SUBSTRING(H.F1056, patindex('%[^0]%',H.F1056), 10) AS Shop_Number
, '000' AS Cashier_Code
, H.F1057 AS Terminal_number
, REPLACE(CONVERT(VARCHAR(10), H.F254, 103), '/', '') AS Todays_Date
, STIME AS Ticket_Time
, H.F1032 AS Ticket_Number
, K.F1063 AS Mode_Of_Payment
, K.F02 AS Mode_Of_Payment_Desc
, CASE WHEN J.F1063 = 117
THEN J.F02
ELSE '' END AS Gift_Number
, CASE WHEN I.F02 = 'TOTAL'
THEN I.F65
ELSE 0 END AS Total_Ticket
FROM [READEJ_H] H
LEFT OUTER JOIN [dbo].[READEJ_I] I
ON (H.F1101 = I.F1101 AND I.F02 = 'TOTAL')
LEFT OUTER JOIN [dbo].[READEJ_I] K
ON (H.F1101=K.F1101 AND K.F1063 BETWEEN 100 AND 199)
LEFT OUTER JOIN [dbo].[READEJ_I] J
ON (H.F1101=J.F1101 AND J.F1063 = 117)
WHERE I.F65 <> CONVERT(DOUBLE PRECISION,0)
How can i extract only the information between the square brackets in the sql select statement.The output should be as below :
2989153053216
Probably the simplest way is to use charindex and substring:
DECLARE #S varchar(100) = 'Gift certificat (-) [2989153053216]'
SELECT SUBSTRING(#S, CHARINDEX('[', #S)+1, CHARINDEX(']', #S) - CHARINDEX('[', #S)-1)
Result: 2989153053216
However, you should be aware that this will raise an error if the string does not contain the delimiters, or if the ] delimiter comes before the [ delimiter.
let the char be s and string be mississsipisssss . The sql should return 5.
I was thinking to makeup something using
regexp_count(string,'s+') would return the number of substrings whith consecutive sequence of s .
REGEXP_INSTR(string,'s',1,m) would return the position of the m'th occurence of char s(starting position of mth sequence)
REGEXP_INSTR(string,'s[^s]',1,m) would return the position of the m'th occurence of char s (ending position of mth sequence)
I havent still come to any solution.But I dont think this is a correct way,as the strings could be of any length, and there could be any number of such consecutive sequences. Could someone give any idea for solution (I am beginner)
Here is a standard solution using a hierarchical query. The CASE expression in the outer query is needed to give the answer "null" when the input string is "null" (otherwise the answer would be 0, and it shouldn't be). I didn't add an ORDER BY clause - you can do so if needed. Good luck!
with
inputs ( str ) as (
select 'mississsipisssss' from dual union all
select null from dual union all
select 'stress' from dual union all
select 'alphabeta' from dual
),
prep ( str, lvl ) as (
select str, level
from inputs
connect by prior str = str
and prior sys_guid() is not null
and regexp_instr(str, 's{' || to_char(level-1) || '}') != 0
)
select str, case when str is not null then max(lvl) - 1 end as max_len
from prep
group by str
;
STR MAX_LEN
---------------- ----------
(null) (null)
alphabeta 0
stress 2
mississsipisssss 5
4 rows selected.
This will work in sql-server 2008 +. The same concept will work in Oracle you just need to add a couple of syntax differences such as SUBSTR instead of SUBSTRING. Here is a quick attempt of converting to Oracle syntax:
CREATE GLOBAL TEMPORARY TABLE TempTable
(String VARCHAR(100)) ON COMMIT PRESERVE ROWS;
INSERT INTO TempTable (String) VALUES ('mississsipisssss');
INSERT INTO #TempTable (String) VALUES ('ssasdfs');
WITH cteTokens (String, IndexNum, Token, CharCount) AS (
SELECT
String
,1 as IndexNum
,SUBSTR(t.String,1,1) as Token
,CASE WHEN SUBSTR(t.String,1,1) = 's' THEN 1 ELSE 0 END As CharCount
FROM
#TempTable t
UNION ALL
SELECT
t.String
IndexNum + 1 as IndexNum
,SUBSTR(t.String,IndexNum + 1,1) as Token
,CASE WHEN SUBSTR(t.String,IndexNum + 1,1) = 's' THEN t.CharCount + 1 ELSE 0 END AS CharCount
FROM
#TempTable s
INNER JOIN cteTokens t
ON s.String = t.String
AND LENGTH(s.String) >= t.IndexNum + 1
)
SELECT
String
,MAX(CharCount)
FROM
cteTokens
GROUP BY
String
;
And Here is a SQL-Server Version
CREATE TABLE #TempTable (String VARCHAR(100))
INSERT INTO #TempTable (String) VALUES ('mississsipisssss')
INSERT INTO #TempTable (String) VALUES ('ssasdfs')
;WITH cteTokens (String, IndexNum, Token, CharCount) AS (
SELECT
t.String
,1 as IndexNum
,SUBSTRING(t.String,1,1) as Token
,CASE WHEN SUBSTRING(t.String,1,1) = 's' THEN 1 ELSE 0 END As CharCount
FROM
#TempTable t
UNION ALL
SELECT
t.String
,IndexNum + 1 as IndexNum
,SUBSTRING(t.String,IndexNum + 1,1) as Token
,CASE WHEN SUBSTRING(t.String,IndexNum + 1,1) = 's' THEN t.CharCount + 1 ELSE 0 END As CharCount
FROM
#TempTable s
INNER JOIN cteTokens t
ON s.String = t.String
AND LEN(s.String) >= t.IndexNum + 1
)
SELECT
String
,MAX(CharCount)
FROM
cteTokens
GROUP BY
String
It is a Recursive Common Table Expression [CTE] that splits the string into character tokens in order of Index Position and tests to see if they are the character you desire. If the token is the character then it builds on the count from the previous token if is character so all you have to do is take the MAX() of the result and you have your answer.
This is not an operation well supported by databases, although Postres definitely has functionality in this area.
If you know there is some limit on the number of substrings of "s"s, then you could do something like this:
select greatest(coalesce(length(regexp(substr(string, '[s]+', 1, 1)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 2)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 3)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 4)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 5)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 6)), 0)
)
This would find the first 6 substrings and then calculate the maximum length.
The alternative is essentially to split the string yourself using connect by or a recursive CTE. However, the above might be sufficient.
I havenĀ“t done any T-SQL before and were wondering how could I change the script below to differentiate between positive and negative values. At the moment it seems to just to add the two together and giving out wrong values.
I would like to add an IF clause that s.summa would follow rules:
e.g
-1 + -1 = -2
1 + -1 = 0
1 + 1 = 2
If I am correct now it is being dealt with "etumerkki", so that if etumerkki variable is 0 s.sum is converted to negative and if etumerkki variable has not been set it remains normal.
SET #stmt = CONCAT( 'INSERT INTO tbl_1 (rivi,rivi_id,isanta_rivi,taso,lihavointi,tili_rivi,otsikko,selite,summa)
SELECT t.rivi , t.rivi_id , t.isanta_rivi , t.taso , t.lihavointi , t.rivi_tyyppi , t.otsikko , t.selite ,
CASE etumerkki
WHEN 0 THEN -1 * IFNULL(SUM(s.summa),0.00)
ELSE IFNULL(SUM(s.summa),0.00)
END AS summa
FROM tase_mem t
LEFT JOIN kuutio_paakirja s ON s.tili = t.tili
WHERE ' , nyk_summa_ehto , '
AND s.kpaikka_id = ' , kpaikka_id , ' AND s.projekti_id = ' , projekti_id , ' ' , isanta_ehto , '
GROUP BY t.rivi , t.rivi_id , t.taso , t.lihavointi , t.rivi_tyyppi , t.etumerkki , t.otsikko , t.selite;');
PREPARE stmt FROM #stmt;
EXECUTE stmt;
Thanks in advance
Not sure if i follow...
SUM()
does indeed evaluate signed numbers correctly. Eg
sum(1, -1) = 0, sum(-1, -1)=-2 and sum(1,1) = 2
See:
select sum(a)
from (
select 1 as a
union all select -1
) i
select sum(a)
from (
select -1 as a
union all select -1
) i
select sum(a)
from (
select 1 as a
union all select 1
) i
However, in your query, you write IFNULL(SUM(s.summa),0.00):
This means that your query first sums all s.summa, and AFTER that evaluates IFNULL.
I suppose you want to evalue whether s.summa is null before you add them together. changing the query to SUM(IFNULL(s.summa),0.00) should give you the proper result.