How to reduce code redundancy in this query? - sql

I've got these two calculated fields in my query:
CASE
WHEN TRN.TOTAL_VALUE_T = 0 THEN '00000000000'
ELSE
CASE
WHEN CC.PORT_CURRENCY1 = 'CAD' THEN RIGHT('00000000000' + REPLACE(LTRIM(STR(TRN.TOTAL_VALUE_T + TRN.TAXES, 11, 2)), '.', ''), 11)
WHEN CC.PORT_CURRENCY1 = 'USD' THEN RIGHT('00000000000' + REPLACE(LTRIM(STR((TRN.TOTAL_VALUE_T + TRN.TAXES) * DBO.fnGetExchangeRate(TRN.TRADE_DATE, 'USD', 'CAD'), 11, 2)), '.', ''), 11)
END
END AS TX_PRIX_CAD,
CASE
WHEN T.TRANS_TYPE in ('ADD','DELIV') THEN
CASE
WHEN (SELECT currencyTitle FROM DBO.GetPrice(TRN.SEC_NO, TRN.TRADE_DATE)) = '' THEN TX_PRIX_CAD
END
END AS TX_MNT_BRUT
You see, the second field (TX_MNT_BRUT) must equal the first one (TX_PRIX_CAD) under certain conditions.
Problem when doing this is SQL is telling me that TX_PRIX_CAD is not a valid column name, I guess because the column name does not exist physically in the table.
How could I achieve this without repeating the code in TX_PRIX_CAD in TX_MNT_BRUT ?
Thanks.

You probably need to nest the select statement e.g.
SELECT <other_columns>, TX_PRIX_CAD,
CASE
WHEN T.TRANS_TYPE in ('ADD','DELIV') THEN
CASE
WHEN (SELECT currencyTitle FROM DBO.GetPrice(TRN.SEC_NO, TRN.TRADE_DATE)) = '' THEN TX_PRIX_CAD
END
END AS TX_MNT_BRUT
FROM (
SELECT
<other columns>,
CASE
WHEN TRN.TOTAL_VALUE_T = 0 THEN '00000000000'
ELSE
CASE
WHEN CC.PORT_CURRENCY1 = 'CAD' THEN RIGHT('00000000000' + REPLACE(LTRIM(STR(TRN.TOTAL_VALUE_T + TRN.TAXES, 11, 2)), '.', ''), 11)
WHEN CC.PORT_CURRENCY1 = 'USD' THEN RIGHT('00000000000' + REPLACE(LTRIM(STR((TRN.TOTAL_VALUE_T + TRN.TAXES) * DBO.fnGetExchangeRate(TRN.TRADE_DATE, 'USD', 'CAD'), 11, 2)), '.', ''), 11)
END
END
END AS TX_PRIX_CAD,
T.TRANS_TYPE
FROM <table_name>
)

Related

How to get per hour in data set?

I'm trying to get data per hour however as I execute, the data for day is displayed in the table. IDC_YMD with per hour result must be in the table and I'm not sure if I have the right SUBSTR(string, start, length).
SELECT EQP_ID, EQP_NAME, 'WorkPreparation' GUBUN,WorkPreparation
CNT,SITE_CODE,GODS_CODE,STEP_NAME,IDC_YMD,IDC_SUMR_UNIT_CODE,MTBI,MTBA
FROM
(
SELECT CASE WHEN WorkPreparation = 0 THEN '-' ELSE EQP_ID END AS EQP_ID, CASE WHEN WorkPreparation =
0 THEN '-' ELSE SUBSTR(EQP_NAME,1,4) END AS EQP_NAME,
WorkPreparation,SITE_CODE,GODS_CODE,STEP_NAME,IDC_YMD,IDC_SUMR_UNIT_CODE,MTBI,MTBA
FROM(
SELECT EQP_ID, EVENT_COMMENT EQP_NAME, SUM(WORK_PRE_CNT) WorkPreparation, A.SITE_CODE
, A.GODS_CODE
, A.EES_STEP_ID AS STEP_NAME
, TO_CHAR(TO_NUMBER(SUBSTR(A.IDC_YMD, 12, 2))) || '/' || TO_CHAR(TO_NUMBER(SUBSTR(A.IDC_YMD, 12,
2))) AS IDC_YMD
, 'D' AS IDC_SUMR_UNIT_CODE
, CASE WHEN (SUM(NVL(A.INTR_CNT, 0)) + SUM(NVL(A.BRDN_CNT, 0))) = 0
THEN ROUND(SUM(NVL(A.OPER_MOP, 0)),1)
ELSE ROUND(SUM(NVL(A.OPER_MOP, 0)) / (SUM(NVL(A.INTR_CNT, 0)) + SUM(NVL(A.BRDN_CNT, 0))) /
60,1)
END AS MTBI
, CASE WHEN (SUM(NVL(A.INTR_CNT, 0)) + SUM(NVL(A.BRDN_CNT, 0)) + SUM(NVL(A.WORK_PRE_CNT, 0)) +
SUM(NVL(A.PROD_CHANGE_CNT, 0)) + SUM(NVL(A.QUAL_EXATN_CNT, 0)) +
SUM(NVL(A.MTR_EXATN_CNT, 0)) + SUM(NVL(A.STEP_CHRC_LOSS_CNT, 0)) +
SUM(NVL(A.IDLE_3MN_UND_EXCPT_CNT, 0))) = 0
THEN 0
ELSE ROUND(SUM(NVL(A.OPER_MOP, 0)) / (SUM(NVL(A.INTR_CNT, 0)) + SUM(NVL(A.BRDN_CNT, 0)) +
SUM(NVL(A.WORK_PRE_CNT, 0)) + SUM(NVL(A.PROD_CHANGE_CNT, 0)) + SUM(NVL(A.QUAL_EXATN_CNT, 0)) +
SUM(NVL(A.MTR_EXATN_CNT, 0)) + SUM(NVL(A.STEP_CHRC_LOSS_CNT,
0)) + SUM(NVL(A.IDLE_3MN_UND_EXCPT_CNT, 0))) / 60,1)
END AS MTBA
FROM IFR_EES_PCL A
WHERE SITE_CODE = 'E502AA'
AND GODS_CODE = 'N5210'
AND MTBI_MNG_YN = 'Y'
AND EES_STEP_ID = 'TP'
AND A.IDC_YMD BETWEEN TO_CHAR(SYSDATE-6, 'YYYYMMDDHH') AND TO_CHAR(SYSDATE, 'YYYYMMDD')
GROUP BY EQP_ID, EVENT_COMMENT,A.SITE_CODE
, A.GODS_CODE
,A.EQP_TYPE
, A.EES_STEP_ID
, TO_CHAR(TO_NUMBER(SUBSTR(A.IDC_YMD, 12, 2)))
, A.IDC_YMD
ORDER BY A.IDC_YMD, MTBI DESC--TO_CHAR(TO_NUMBER(SUBSTR(A.IDC_YMD, 12, 2)))
))
WHERE ROWNUM <= 10
and EQP_NAME like 'TA%'
Thank you!

Display Column value according to need in sql

if i have a column in which ten digit values occurs like Column A = 11111000 so how to show this value in sql like (List,Add,Edit,Delete,Export) in sql.
there is a condition means if first position have 1 then it show List, If second Position have 1 it show Add, third position have 1 then Edit, fourth position have 1 then Delete, fifth position have 1 then Export.
If the value is a string, you can do:
select stuff( ((case when substring(a, 1, 1) = 1 then ',List' else '' end) +
(case when substring(a, 2, 1) = 1 then ',Add' else '' end) +
. . .
), 1, 1, '')
The logic is similar for bitwise operators:
select stuff( ((case when a & 2^9 then ',List' else '' end) +
(case when 2 & 2^8 then ',Add' else '' end) +
. . .
), 1, 1, '')
Maybe Substring function can help you to identify these values
select
id, ColumnA,
case when substring(ColumnA,1,1) = '1' then 'X' end as List,
case when substring(ColumnA,2,1) = '1' then 'X' end as [Add],
case when substring(ColumnA,3,1) = '1' then 'X' end as Edit,
case when substring(ColumnA,4,1) = '1' then 'X' end as [Delete],
case when substring(ColumnA,5,1) = '1' then 'X' end as [Export]
from Table1
I update the query according to comment
select
id, ColumnA,
stuff(
case when substring(ColumnA,1,1) = '1' then ',List' else '' end +
case when substring(ColumnA,2,1) = '1' then ',Add' else '' end +
case when substring(ColumnA,3,1) = '1' then ',Edit' else '' end +
case when substring(ColumnA,4,1) = '1' then ',Delete' else '' end +
case when substring(ColumnA,5,1) = '1' then ',Export' else '' end
,1,1,''
)
from Table1

sql server Insert if not exists and get the inserted id into another table

I am new to SQL Server and working on a project to record logs.
The table has a URL column varchar(max) which has repeating value. I created another table which stores only the distinct URLs and the IDs are stored in the main table
Here is my stored procedure to do this:
CREATE TABLE #TestData (
logdate DATETIME,
id CHAR(15),
value VARCHAR(max)
)
DECLARE #sql VARCHAR(max)
SET #sql = 'BULK INSERT [dbo].[#TestData] FROM ''' + #pfile + ''' WITH (
firstrow = 2,
fieldterminator = ''\t'',
rowterminator = ''\n''
)'
EXEC (#sql)
create table #testurl(fld varchar(max))
INSERT INTO #testurl(fld) (
SELECT distinct (
CASE
WHEN (PATINDEX('%url="%', value) > 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%url="%', value) + 5), (CHARINDEX('"', value, (PATINDEX('%url="%', value) + 5)) - (PATINDEX('%url="%', value) + 5))), ''))
END
) FROM #TestData )
INSERT INTO url (urlvalue) (
SELECT tu.fld FROM #testurl tu WHERE NOT EXISTS (
SELECT urlid
FROM url u
WHERE u.urlvalue = tu.fld))
INSERT INTO [Cyberoam].[dbo].[logmst] (
DATETIME,
c1c2,
c3c4,
c5c6,
c7,
c8to12,
STATUS,
username,
usergrp,
application,
category,
categorytype,
urlid,
recvbytes,
sentbytes,
fw_rule_id,
srcip,
dstip,
contenttype
)
SELECT logdate,
SUBSTRING(value, (PATINDEX('%log_id=%', value) + 7), 2),
SUBSTRING(value, (PATINDEX('%log_id=%', value) + 9), 2),
SUBSTRING(value, (PATINDEX('%log_id=%', value) + 11), 2),
SUBSTRING(value, (PATINDEX('%log_id=%', value) + 13), 1),
SUBSTRING(value, (PATINDEX('%log_id=%', value) + 14), 5),
CASE
WHEN (SUBSTRING(value, (PATINDEX('%status="%', value) + 8), (CHARINDEX('"', value, (PATINDEX('%status="%', value) + 8)) - (PATINDEX('%status="%', value) + 8)))) = 'Allow'
THEN '1'
WHEN (SUBSTRING(value, (PATINDEX('%status="%', value) + 8), (CHARINDEX('"', value, (PATINDEX('%status="%', value) + 8)) - (PATINDEX('%status="%', value) + 8)))) = 'Deny'
THEN '0'
ELSE NULL
END,
CASE
WHEN (ISNULL(PATINDEX('%user_name="%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%user_name="%', value) + 11),(CHARINDEX('"', value, (PATINDEX('%user_name="%', value) + 11)) - (PATINDEX('%user_name="%', value) + 11))), ''))
ELSE NULL
END,
CASE
WHEN (isnull(PATINDEX('%user_gp="%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%user_gp="%', value) + 9), (CHARINDEX('"', value, (PATINDEX('%user_gp="%', value) + 9)) - (PATINDEX('%user_gp="%', value) + 9))), ''))
ELSE NULL
END,
CASE
WHEN (isnull(PATINDEX('%application="%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%application="%', value) + 13), (CHARINDEX('"', value, (PATINDEX('%application="%', value) + 13)) - (PATINDEX('%application="%', value) + 13))), ''))
WHEN (isnull(PATINDEX('%application_name="%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%application_name="%', value) + 18), (CHARINDEX('"', value, (PATINDEX('%application_name="%', value) + 18)) - (PATINDEX('%application_name="%', value) + 18))), ''))
ELSE NULL
END,
CASE
WHEN (isnull(PATINDEX('%category="%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%category="%', value) + 10), (CHARINDEX('"', value, (PATINDEX('%category="%', value) + 10)) - (PATINDEX('%category="%', value) + 10))), ''))
ELSE NULL
END,
CASE
WHEN (isnull(PATINDEX('%category_type="%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%category_type="%', value) + 15), (CHARINDEX('"', value, (PATINDEX('%category_type="%', value) + 15)) - (PATINDEX('%category_type="%', value) + 15))), ''))
ELSE NULL
END,
(
SELECT urlid
FROM url
WHERE urlvalue = (
CASE
WHEN (isnull(PATINDEX('%url="%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%url="%', value) + 5), (CHARINDEX('"', value, (PATINDEX('%url="%', value) + 5)) - (PATINDEX('%url="%', value) + 5))), ''))
ELSE NULL
END
)
),
CASE
WHEN (isnull(PATINDEX('%recv_bytes=%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%recv_bytes=%', value) + 11), (PATINDEX('%[^0-9]%', (nullif(SUBSTRING(value, (PATINDEX('%recv_bytes=%', value) + 11), 20), ''))))), ''))
ELSE NULL
END,
CASE
WHEN (isnull(PATINDEX('%sent_bytes=%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%sent_bytes=%', value) + 11), (PATINDEX('%[^0-9]%', (nullif(SUBSTRING(value, (PATINDEX('%sent_bytes=%', value) + 11), 20), ''))))), ''))
ELSE NULL
END,
CASE
WHEN (isnull(PATINDEX('%fw_rule_id=%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%fw_rule_id=%', value) + 11), (CHARINDEX(' ', value, (PATINDEX('%fw_rule_id=%', value) + 11)) - (PATINDEX('%fw_rule_id=%', value) + 11))), ''))
ELSE NULL
END,
CASE
WHEN (isnull(PATINDEX('%src_ip=%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%src_ip=%', value) + 7), (CHARINDEX(' ', value, (PATINDEX('%src_ip=%', value) + 7)) - (PATINDEX('%src_ip=%', value) + 7))), ''))
ELSE NULL
END,
CASE
WHEN (isnull(PATINDEX('%dst_ip=%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%dst_ip=%', value) + 7), (CHARINDEX(' ', value, (PATINDEX('%dst_ip=%', value) + 7)) - (PATINDEX('%dst_ip=%', value) + 7))), ''))
ELSE NULL
END,
CASE
WHEN (isnull(PATINDEX('%contenttype="%', value), 0) <> 0)
THEN (nullif(SUBSTRING(value, (PATINDEX('%contenttype="%', value) + 13), (CHARINDEX('"', value, (PATINDEX('%contenttype="%', value) + 13)) - (PATINDEX('%contenttype="%', value) + 13))), ''))
ELSE NULL
END
FROM #TestData
This code works fine, but the problem is that the time taken to run bulk insert with a file of around 5 k records increases gradually( as the URL table increases reaching 20 mins with ~ 5k records in it ).Many such file will be inserted.
Need your suggestions as how I can improve the performance or if am I doing something wrong
Appreciate your help very much. Thank you!
Note : It take around 4-7 secs if the URL column is in the same table.
will it make any performance difference if its in the same table or separated?
Got a solution for this.Here is the solution if someone needs it.
The time taken was long because of the URL being varchar(max).
I deleted the clustered PK index.Added a new column for checksum of url and created a clustered index on it.
And changed :
SELECT urlid
FROM url
WHERE urlvalue = (#value)
to :
SELECT urlid
FROM url
WHERE checksum_urlvalue = checksum(#value) nad urlvalue = (#value)
This reduced the execution time to 7-8 secs.
Thank you all for your responses.
Happy coding :)

How to convert nvarchar m/d/yy to mm/dd/yyyy in SQL Server?

Input is nvarchar that varies in format from m/d/yy to mm/dd/yyyy. How can this be converted to mm/dd/yyyy in SQL? So far the CONVERT() function works for the format m/d/yyyy but errors for m/d/yy.
Cast it as a date like so:
cast(#m + '/' + #d + '/' + #y as datetime)
or similarly
cast('m/d/yy' as datetime)
cast(Fieldnamehere as datetime)
update table_name set column_name = convert(varchar,cast(column_name as date),101) or if a select statment select convert(varchar,cast(column_name as date),101)
There's usually some additional nuances in the data, but here's a starter template I've been able to come up with... Just replace the debug text with convert(datetime2, [DateNVarChar], 101).
CASE
-- x/y/zzzz to xx/yy/zzzz
WHEN SUBSTRING([DateNVarChar], 2, 1) = '/' AND SUBSTRING([DateNVarChar], 4, 1) = '/' THEN
'x/y/zzzz: ' + '0' + SUBSTRING([DateNVarChar], 1, 2) + '0' + SUBSTRING([DateNVarChar], 3, 20)
-- xx/y/zzzz to xx/yy/zzzz
WHEN SUBSTRING([DateNVarChar], 3, 1) = '/' AND SUBSTRING([DateNVarChar], 5, 1) = '/' THEN
'xx/y/zzzz: ' + SUBSTRING([DateNVarChar], 1, 3) + '0' + SUBSTRING([DateNVarChar], 4, 20)
-- x/yy/zzzz to xx/yy/zzzz
WHEN SUBSTRING([DateNVarChar], 2, 1) = '/' AND SUBSTRING([DateNVarChar], 5, 1) = '/' THEN
'x/yy/zzzz: ' + '0' + [DateNVarChar]
ELSE
'Normal: ' + [DateNVarChar]
END as [FormattedDate]

Split a VARCHAR in DB2 to retrieve a value inside

I have a VARCHAR column that contains 5 informations (2 CHAR(3) and 3 TIMESTAMP) separated with '$'.
CREATE TABLE MYTABLE (
COL VARCHAR(256) NOT NULL
);
INSERT INTO MYTABLE
VALUES
( 'AAA$000$2009-10-10 10:50:00$null$null$null' ),
( 'AAB$020$2007-04-10 10:50:00$null$null$null' ),
( 'AAC$780$null$2007-04-10 10:50:00$2009-04-10 10:50:00$null' )
;
I would like to extract the 4th field ...
'AAA$000$2009-10-10 10:50:00$null$null$null'
^^^^ this field
... to have something like
SELECT SPLIT(COL, '$', 4) FROM MYTABLE
1
-----
'null'
'null'
'2009-04-10 10:50:00'
I'm searching, in that order :
A DB2 build-in string function
An embeddable statement such as SUBSTR(COL, POSSTR(COL)+1)...
An user defined function that behaves like SPLIT
Precision : Yes, I do know that it's not a good idea to have such columns...
CREATE FUNCTION split(pos INT, delimeter CHAR, string VARCHAR(255))
LANGUAGE SQL
RETURNS VARCHAR(255)
DETERMINISTIC NO EXTERNAL ACTION
BEGIN ATOMIC
DECLARE x INT;
DECLARE s INT;
DECLARE e INT;
SET x = 0;
SET s = 0;
SET e = 0;
WHILE (x < pos) DO
SET s = locate(delimeter, string, s + 1);
IF s = 0 THEN
RETURN NULL;
END IF;
SET x = x + 1;
END WHILE;
SET e = locate(delimeter, string, s + 1);
IF s >= e THEN
SET e = LENGTH(string) + 1;
END IF;
RETURN SUBSTR(string, s + 1, e - s -1);
END!
Usage:
SELECT split(3,'$',col) from mytable; -- or
SELECT split(0,'-', 'first-second-third') from sysibm.sysdummy1;
SELECT split(0,'-', 'returns this') from sysibm.sysdummy1;
SELECT split(1,'-', 'returns null') from sysibm.sysdummy1;
I am sure there is a better way to write this, but here is 1 (SQL) solution for the simple case given. It could be rewritten as a stored procedure to look for any arbitrary string. There may also be some 3rd party tools/extensions to help out w/ the split you want...
select
locate('$', col, (locate('$',col, (locate('$',col) +1))) + 1) as poss3rdDollarSign, -- position of 3rd dollar sign
locate('$', col, (locate('$', col, (locate('$',col, (locate('$',col) +1))) + 1)) + 1) as poss4thDollarSign, -- position of 4th dollar sign
(locate('$', col, (locate('$', col, (locate('$',col, (locate('$',col) +1))) + 1)) + 1)) -
(locate('$', col, (locate('$',col, (locate('$',col) +1))) + 1)) - 1 as stringLength,-- length of string between 3rd and 4th dollar sign
substr(col, locate('$', col, (locate('$',col, (locate('$',col) +1))) + 1) + 1, (locate('$', col, (locate('$', col, (locate('$',col, (locate('$',col) +1))) + 1)) + 1)) -
(locate('$', col, (locate('$',col, (locate('$',col) +1))) + 1)) - 1) as string
from mytable
try this, it works!
CREATE FUNCTION SPLIT( P_1 VARCHAR(3200),
P_2 VARCHAR(200))
RETURNS TABLE(P_LIST VARCHAR(3200))
SPECIFIC SPLIT
LANGUAGE SQL
MODIFIES SQL DATA
NO EXTERNAL ACTION
F1: BEGIN
return
with source(str, del) as
(select p_1, p_2 from sysibm.sysdummy1),
target(str, del) as
(select source.str, source.del from source
where length(source.str) > 0
union all
select
(case when (instr(target.str, target.del) > 0)
then substr(target.str,
instr(target.str, target.del)+1,
length(target.str)-instr(target.str, target.del)) else null end),
(case when (instr(target.str, target.del) > 0)
then target.del else null end)
from target
where length(target.str) > 0
)
select str from target
where str is not null;
END
If your DB2's version can do it, you can use then LOCATE_IN_STRING function for to found position of your separator. The LOCATE_IN_STRING function returns the starting position of a string and enable you to choice the Nth instance. You can found documentation of this function here
For your example, you can use this code :
select
substring(col, LOCATE_IN_STRING(col, '$', 1, 3), LOCATE_IN_STRING(col, '$', 1, 4) - LOCATE_IN_STRING(col, '$', 1, 3))
from MYTABLE
substr(e.data,1,13) as NNSS,
substring(e.data, LOCATE_IN_STRING(e.data, ';', 1, 1, CODEUNITS32)+1, (LOCATE_IN_STRING(e.data, ';', 1, 2, CODEUNITS32) - LOCATE_IN_STRING(e.data, ';', 1, 1, CODEUNITS32)-1) ) as Name,
substring(e.data, LOCATE_IN_STRING(e.data, ';', 1, 2, CODEUNITS32)+1, (LOCATE_IN_STRING(e.data, ';', 1, 3, CODEUNITS32) - LOCATE_IN_STRING(e.data, ';', 1, 2, CODEUNITS32)-1) ) as Vorname,
substring(e.data, LOCATE_IN_STRING(e.data, ';', 1, 3, CODEUNITS32)+1, (LOCATE_IN_STRING(e.data, ';', 1, 4, CODEUNITS32) - LOCATE_IN_STRING(e.data, ';', 1, 3, CODEUNITS32)-1) ) as Grund