WITH Clause - temporary table to create - sql

I want to create a temporary table.
select * from TFW_ARCHIVETRANSACTION
where TYPE = 'openAccountTransferLifeCycle' and STATUS = 5 and
to_char(substr(
TRANSACTIONDATA,
instr(TRANSACTIONDATA,'<ns:CredentialFunction>') + length('<ns:CredentialFunction>'),
instr(substr(
TRANSACTIONDATA,
instr(TRANSACTIONDATA,'<ns:CredentialFunction>') + length('<ns:CredentialFunction>')
), '</ns:CredentialFunction>') - 1
)) = 'OpenCurrentAccount';
I am trying like:
with openAccountTransferLifeCycle_c AS (
select * from TFW_ARCHIVETRANSACTION
where TYPE = 'openAccountTransferLifeCycle'and STATUS = 5 and
to_char(substr(
TRANSACTIONDATA,
instr(TRANSACTIONDATA,'<ns:CredentialFunction>') + length('<ns:CredentialFunction>'),
instr(substr(
TRANSACTIONDATA,
instr(TRANSACTIONDATA,'<ns:CredentialFunction>') + length('<ns:CredentialFunction>')
), '</ns:CredentialFunction>') - 1
)) = 'OpenCurrentAccount'
);
but it is not working.
Where is wrong?

what you are trying to create is not temporary table,you are trying to create CTE which can be thought of like a view but only it's not materialized and scope is immediate..
You are almost there except selecting part and make sure you add ; to start of cte
;with openAccountTransferLifeCycle_c
AS
(select * from TFW_ARCHIVETRANSACTION
where TYPE = 'openAccountTransferLifeCycle'and STATUS = 5
and
to_char(substr(TRANSACTIONDATA, instr(TRANSACTIONDATA,'<ns:CredentialFunction>') + length('<ns:CredentialFunction>'),
instr(substr(TRANSACTIONDATA,
instr(TRANSACTIONDATA,'<ns:CredentialFunction>') + length('<ns:CredentialFunction>')),
'</ns:CredentialFunction>') - 1)) = 'OpenCurrentAccount');
select * from openAccountTransferLifeCycle_c

Related

Iterate each row and perform update accordingly

I have PostgreSQL SQL that should look for a backslash in a column called source_username and if it finds the backslash, it should replace the current value of the source_username column with the same value without the characters before the backslash.
For example:
before source_username: domain\username
after source_username: username
with os_user as (
select source_username from itpserver.managed_incidents mi;
),
osUserWithoutDomain as (
select (
case when (select * from os_user) ilike '%\\%' and (select position('-' in (select * from os_user))>= 1) and (select length((select * from os_user)) != (select position('-' in (select * from os_user))) + 1)
then (
select substring(
(select * from os_user),(select position('\' in (select * from os_user)) + 1),(select length((select * from os_user)) - 1)
))
else ((select * from os_user))
end
)
)
UPDATE itpserver.managed_incidents SET source_username = replace(source_username, (select * from os_user), (select * from osUserWithoutDomain)),
description = replace(description , (select * from os_user), (select * from osUserWithoutDomain)),
additional_info = replace(additional_info , (select * from os_user), (select * from osUserWithoutDomain)),
typical_behavior = replace(typical_behavior , (select * from os_user), (select * from osUserWithoutDomain)),
raw_description = replace(raw_description , (select * from os_user), (select * from osUserWithoutDomain));
This SQL works fine when I have only one row in the table.
If I have multiple rows, I need to specify the row that I want to work with by adding where id = <id>
I wish to iterate all the relevant rows (all the rows that source_username contains backslash) and on each row to perform the SQL above.
I tried to do this with LOOP:
create or replace function fetcher()
returns void as $$
declare
emp record;
begin
for emp in select *
from itpserver.managed_incidents
order by id
limit 10
loop
raise notice '%', emp.id;
<my sql> where id = emp.id
end loop;
end;
$$language plpgsql;
select fetcher();
However, I get an error because I don't think it likes the 'with' statement.
Any idea how can I do it?
It's far simpler than that. You need to use the SUBSTR and STRPOS functions. Take a look at the results of this query.
https://dbfiddle.uk/9-yPKn6E
with os_user (source_username) as (
select 'domain\username'
union select 'mydomain\joe'
union select 'janet'
)
select u.source_username
, strpos(u.source_username, '\')
, substr(u.source_username, strpos(u.source_username, '\') + 1)
from os_user u
source_username
strpos
substr
domain\username
7
username
janet
0
janet
mydomain\joe
9
joe
What you need is:
UPDATE itpserver.managed_incidents
SET source_username = substr(source_username, strpos(source_username, '\') + 1)
, description = replace(description , source_username, substr(source_username, strpos(source_username, '\') + 1))
, additional_info = replace(additional_info , source_username, substr(source_username, strpos(source_username, '\') + 1))
, typical_behavior = replace(typical_behavior , source_username, substr(source_username, strpos(source_username, '\') + 1))
, raw_description = replace(raw_description , source_username, substr(source_username, strpos(source_username, '\') + 1));
This is based on lengthy experience with SQL Server and some quick document searches for Postgresql. The UPDATE statement may not work as I expect.
SQL by design/default works on complete data sets. It thus eliminates LOOPS entirely from the language - they are not needed. (Well not quite there are recursive queries). Your task is accomplished in a single update statement with a simple regular expression. See documentation String Functions:
update managed_incidents
set source_username = regexp_replace(source_username,'.*\\(.*)','\1');
Demo here.
Main Take away: Drop procedural logic terminology (for, loop, if then, ...) from your SQL vocabulary. (you choose alternatives with case.)

SQL HIVE Conversion

I'm trying to convert a piece of SQL code to HiveQL, and it's not working as expected.
Please find below the code snippet in SQL that I'm attempting to convert:
SQL Code:
UPDATE
C
SET
C.prod_l = P.prod_l, C.numprod = P.numprod, C.prod_cng = P.prod_cng
FROM
[cnc].dbo.[c_cnc_analysis] C
LEFT JOIN
(
SELECT
X.*,
Len(prod_l) - Len(Replace(prod_l, ' ~ ', ' ')) + 1 AS NumProd,
CASE
WHEN
Len(prod_l) - Len(Replace(prod_l, ' ~ ', ' ')) + 1 = 1
THEN
0
ELSE
1
END
AS PROD_CNG
FROM
(
SELECT DISTINCT
ST2.uitid,
Substring((
SELECT
' ~ ' + ST1.product_id AS [text()]
FROM
(
SELECT
[uitid],
[product_id]
FROM
dbo.[c_cnc_dedup_bse]
GROUP BY
[uitid],
[product_id]
)
ST1
WHERE
ST1.uitid = ST2.uitid
ORDER BY
ST1.uitid FOR xml path ('')), 4, 1000 ) [PROD_L]
FROM
(
SELECT
[uitid],
[product_id]
FROM
dbo.[c_cnc_dedup_bse]
GROUP BY
[uitid],
[product_id]
)
ST2
)
X
)
P
ON C.uitid = P.uitid;
Converted HIVE Query:
create
or replace view prd_temp as
SELECT
`UITID`,
`PRODUCT_ID`
FROM
`C_CNC_DEDUP_BSE`
GROUP BY
`UITID`,
`PRODUCT_ID`;
create
or replace view prd_temp2 as
SELECT
`UITID`,
`PRODUCT_ID`
FROM
`C_CNC_DEDUP_BSE`
GROUP BY
`UITID`,
`PRODUCT_ID`;
create
or replace view prd_temp3 as
SELECT
st1.`uitid`,
concat(' ~ ', st1.`PRODUCT_ID`) AS `text()`
FROM
prd_temp ST1
left join
prd_temp2 st2
on ST1.`UITID` = ST2.`UITID`
where
st1.`UITID` = st2.`UITID`
ORDER BY
ST1.`UITID`;
create
or replace view prd_temp4 as
SELECT
st1.`uitid`,
concat_ws('''', `text()`)
FROM
prd_temp3 ST1
ORDER BY
ST1.`UITID`;
create
or replace view st2 as
SELECT DISTINCT
`UITID`,
SUBSTRING(`_c1` , 4, 1000) as `PROD_L`
FROM
prd_temp4;
create
or replace view x as
SELECT
*,
LENGTH(PROD_L) - LENGTH(REPLACE(PROD_L, ' ~ ', ' ')) + 1 as NumProd,
CASE
WHEN
LENGTH(PROD_L) - LENGTH(REPLACE(PROD_L, ' ~ ', ' ')) + 1 = 1
then
0
ELSE
1
END
as PROD_CNG
from
ST2;
create table C_CNC_ANALYSIS1 as
select
c.*,
P.numprod as numprod,
p.prod_cng as prod_cng,
p.prod_l as prod_l
from
`C_CNC_ANALYSIS` C
LEFT JOIN
X P
ON C.UITID = P.UITID ;
SELECT
*
from
c_cnc_analysis1 limit 100;
Appreciate all the help with this. I think the code converted for the XML path is not working in HIVE, since I'm getting multiple UITIDs (key) and the information in separate rows rather than just one single record per UITID.
Thank You,
Viswanath Sitaraman

SQL joins with mulitple where conditions

I have one table that looks like this:
[Jobs]
+-----+-------+---------+
+ ID + Title + Active +
+-----+-------+---------+
+ 1 + Admin + 0 +
+-----+-------+---------+
+ 2 + Mgr + 1 +
+-----+-------+---------+
+ 3 + Emp + 0 +
+-----+-------+---------+
[JobsTxt]
+-------+-------+---------+
+ JobID + Text + Type +
+-------+-------+---------+
+ 1 + test + 1 +
+-------+-------+---------+
+ 1 + test2 + 1 +
+-------+-------+---------+
+ 1 + test3 + 2 +
+-------+-------+---------+
+ 3 + test + 1 +
+-------+-------+---------+
I want to write a query that gives me the Text entries from the JobsTxt table that have Type= 1 and Active=0 in the Jobs table, where JobsTxt.JobID = Jobs.ID
So it'd be something like:
Select [JobsTxt].Text from [JobsText] left join [Jobs] on [JobsTxt].JobId = [Jobs].ID where [JobsTxt].Type = 1 and [Jobs].Active = 0
I'm very new to joins and queries like this, so any help is appreciated!
EXISTS are good if you dont require a JOIN, meaning you only need fields from one of the tables.
SELECT jt.Text
FROM [JobsText] jt
WHERE jt.Type = 1
AND EXISTS
(
SELECT 1
FROM [Jobs] j
WHERE j.ID = jt.JobID
AND j.Active = 0
);
Please excuse, I am not allowed to comment directly on your question. So, let me just put it here, even as I think this may not qualify as an answer.
To me, your SQL statement looks perfectly okay and should deliver what you described. Maybe you could help us out and give some information on the SQL dialect involved (i.e., what database system you are running and what version)?
edit:
it seems you do have a typo:
[...] from [JobsText] [...]
↑ - should there be an 'e'?
Thank you.
Please make use of below query:
DECLARE #Jobs TABLE (ID INT, Title VARCHAR(10), Active BIT )
INSERT INTO #Jobs VALUES
(1,'Admin',0),
(2,'Mgr',1),
(3,'Emp',0)
DECLARE #Jobtxt TABLE ( JobID INT, [Text] VARCHAR(10), [Type] INT)
INSERT INTO #Jobtxt VALUES
(1,'test',1),
(1,'test2',1),
(1,'test3',2),
(3,'test',1)
SELECT
Jt.JobID,Jt.[Text]
FROM
#Jobtxt Jt INNER JOIN #Jobs J ON Jt.JobID = J.ID
WHERE
J.Active = 0 AND Jt.[Type] =1

SQL query returns multiple rows when trying to find specific value

I have 2 tables. One is called "Tasks" and the other one is called "TaskDescription"
in my "Task" the setup looks like this:
"taskID(primary)","FileID","TaskTypeID" and a bunch of other columns irrelevant.
Then in my "TaskDescription", the setup looks like:
"TaskTypeID", "TaskTypeDesc"
so for example if TaskTypeID is 1 , then the description would be"admin"
or if TaskTypeID is 2, then TaskTypeDesc would be "Employee" etc.
The two tables have a relationship on the primary/foreign key "TaskTypeID".
What I am trying to do is get a task id, and the TaskDesc where the FileID matches the #fileID(which I pass in as a param). However in my query I get multiple rows returned instead of a single row when trying to obtain the description.
this is my query:
SELECT taskid,
( 'Task ID: '
+ Cast(cf.taskid AS NVARCHAR(15)) + ' - '
+ Cast((SELECT DISTINCT td.tasktypedesc FROM casefiletaskdescriptions
td JOIN
casefiletasks cft ON td.tasktypeid=cft.tasktypeid WHERE cft.taskid =
1841 )AS
NVARCHAR(100))
+ ' - Investigator : ' + ( Cast(i.fname AS NVARCHAR(20)) + ' '
+ Cast(i.lname AS NVARCHAR(20)) ) ) AS
'Display'
FROM casefiletasks [cf]
JOIN investigators i
ON CF.taskasgnto = i.investigatorid
WHERE cf.fileid = 2011630988
AND cf.concluded = 0
AND cf.progressflag != 'Conclude'
I am trying to get the output to look like "Task ID: 1234 - Admin - Investigator : John Doe". However I am having trouble on this part:
CAST((select DISTINCT td.TaskTypeDesc from CaseFileTaskDescriptions td
JOIN CaseFileTasks cft ON td.TaskTypeID=cft.TaskTypeID
where cft.TaskID =1841 )as nvarchar(100))
This seems to work but the problem is I have to hard code the value "1841" to make it work. Is there a way to assign a "taskID" variable with the values being returned from the TaskID select query, or will it not work since I think sql runs everything at once instead of line by line.
EDIT-this is in Microsoft SQL Server Management Studio 2008
You can dynamically reference a column that exists in your FROM set. In this case, it would be any column from casefiletasks or investigators. You would replace 1841 with the table.column reference.
Update
Replacing your static integer with the column reference, your query would look like:
SELECT taskid,
( 'Task ID: '
+ Cast(cf.taskid AS NVARCHAR(15)) + ' - '
+ Cast((SELECT DISTINCT td.tasktypedesc FROM casefiletaskdescriptions
td JOIN
casefiletasks cft ON td.tasktypeid=cft.tasktypeid WHERE cft.taskid =
cf.taskid )AS
NVARCHAR(100))
+ ' - Investigator : ' + ( Cast(i.fname AS NVARCHAR(20)) + ' '
+ Cast(i.lname AS NVARCHAR(20)) ) ) AS
'Display'
FROM casefiletasks [cf]
JOIN investigators i
ON CF.taskasgnto = i.investigatorid
WHERE cf.fileid = 2011630988
AND cf.concluded = 0
AND cf.progressflag != 'Conclude'
Would this work as your inner query?
SELECT DISTINCT td.TaskTypeDesc FROM CaseFileTaskDescriptions td
JOIN CaseFileTasks cft ON td.TaskTypeID = cft.TaskTypeID
WHERE cft.TaskID = cf.TaskID
Why not just do another join instead of a subquery?
SELECT taskid,
( 'Task ID: '
+ Cast(cf.taskid AS NVARCHAR(15)) + ' - '
+ Cast(td.tasktypedesc AS NVARCHAR(100))
+ ' - Investigator : ' + ( Cast(i.fname AS NVARCHAR(20)) + ' '
+ Cast(i.lname AS NVARCHAR(20)) ) ) AS
'Display'
FROM casefiletasks [cf]
JOIN investigators i
ON CF.taskasgnto = i.investigatorid
JOIN casefiletaskdescriptions td
ON td.tasktypeid = cf.tasktypeid
WHERE cf.fileid = 2011630988
AND cf.concluded = 0
AND cf.progressflag != 'Conclude'

SQL - displaying row where the next numeric value is also available

I have the following query:
SELECT CAST(year_week AS NUMERIC) as year_week FROM web_details where location = ''JF'' AND property_id = ''FARM''
which produces the following results.
YEAR_WEEK
201035
201036
201037
201039
201041
201044
201045
201048
What I actually want is to produce a set of results which only displays values if the consecutive value is available - so producing the following results...
YEAR_WEEK
201035
201036
201044
To add another spanner into the works, the column year_week is not a numeric value so has needed to be converted.
Thanks
SELECT
CAST(year_week AS NUMERIC) as year_week
FROM
web_details wd
WHERE
EXISTS(
SELECT
year_week
FROM
web_details wd2
WHERE
wd2.year_week = CASE(RIGHT(wd.year_week, 2))
WHEN '48' THEN CAST((CAST(LEFT(wd.year_week,4) AS INT) + 1) AS VARCHAR(4)) + '01'
ELSE LEFT(wd.year_week,4) + CAST((CAST(RIGHT(wd.year_week,2) AS INT) + 1) AS VARCHAR(2))
END
)
Basically, my approach is that you calculate another column that contains the next year_week value, and the join it to itself.
WITH myCTE AS (
SELECT year_week, CONVERT(VARCHAR(4),DATEPART(year,CONVERT(datetime,LEFT(year_week,4)) + (RIGHT(year_week,2) + 1) * 7 )) + RIGHT( '000' + CONVERT(VARCHAR(2),DATEPART(MONTH,CONVERT(datetime,LEFT(year_week,4)) + (RIGHT(year_week,2) + 1) * 7)),2) next_year_week
FROM web_details
WHERE ..........
)
SELECT T1.year_week, T2.year_week
FROM myCTE T1
INNER JOIN myCTE T2 ON T1.next_year_week = T2.year_week