I'm having a trouble with saving multiple rows of a query into single one using CLOB.
I've tried this method suggested at ASK TOM https://asktom.oracle.com/pls/apex/f?p=100:11:::NO::P11_QUESTION_ID:9537158500346658848
but i think i'm lacking some knowledge to properly bind variables of my query.
Could you please help me? or maybe there is another option for this query to be compressed into single row using a CLOB
Here is the query in question
Select '<?xml version="1.0" encoding="UTF-8"?>'||chr(10)||
'<OtherServices ServiceMonth="'|| to_char(framework.dim_calendar_pkg.get_startdate(FRAMEWORK.CTL_Session_Parameters_PKG.Get_BillingPeriod()),'YYYYMM')||'" Source ="CLIENT" UniqueFileID ="ID0000036">' as XML
from dual
union all
select CAST(XML as varchar2(2000)) as XML from (
with CTE as
(SELECT R.BS_TEXT AS BillingDriver
, F.CI_NAME AS Signum
, 1 AS Quantity -- not F.Quantity, as even non-billable should have quantity 1
, CASE WHEN F.QUANTITY=0
THEN 'No'
ELSE 'Yes'
END AS Billable
FROM CLIENT.FACTS F
JOIN CLIENT.DIM_RESOURCEUNITS_VW R ON F.RU_ID = R.RU_ID
WHERE F.BILLINGPERIOD = FRAMEWORK.CTL_Session_Parameters_PKG.Get_BillingPeriod()
AND F.BILLINGPERIOD = F.SERVICEPERIOD
AND F.INPUT_SOURCE IN ('CLIENT_CVS_NONPDV','CLIENT_CVS_PDV','CLIENT_CVS_PV')
)
SELECT
XMLSERIALIZE(document
XMLElement("Service",
XMLForest (C.BillingDriver AS "BillingDriver",
C.Signum AS "Signum",
C.Quantity AS "Quantity",
C.Billable AS "Billable")
)
indent size=2) XML
FROM CTE C)
UNION ALL
Select '</OtherServices>' AS XML from dual;
SELECT '201904' AS ServiceMonth
, 'CLIENT' AS Source
, 'ID0000038' AS UniqueFileID
, 'ViCS_MWPII_user' AS BillingDriver
, VM.SIGNUM AS "Signum-ID"
, 1 AS Quantity
, 'Yes' AS Billable
FROM CLIENT.REF_CVS_VICS_MATRIX_VW VM
WHERE VM.ACCESS_TO_VICS_BASE = 1
AND (VM.ACCESS_TO_VICS_DESTKOP_EMEA = 1 OR VM.ACCESS_TO_VICS_DESTKOP_AMCS = 1 OR VM.ACCESS_TO_VICS_DESTKOP_APAC = 1)
AND EXISTS (SELECT 1 from CLIENT.FACTS F
WHERE F.BILLINGPERIOD = FRAMEWORK.CTL_Session_Parameters_PKG.Get_BillingPeriod()
AND F.BILLINGPERIOD = F.SERVICEPERIOD
AND F.INPUT_SOURCE IN ('CLIENT_MWP2_OPER','CLIENT_MWP2_COMP')
AND UPPER(F.CURRENT_USER) = UPPER(VM.SIGNUM))
UNION ALL
-- Signums with VICS_BASE and one of regional VICS_DESKTOPS, but without user in MWPII
SELECT '201904' AS ServiceMonth
, 'CLIENT' AS Source
, 'ID0000038' AS UniqueFileID
, 'ViCS_PV' AS BillingDriver
, VM.SIGNUM AS "Signum-ID"
, 1 AS Quantity
, 'Yes' AS Billable
FROM CLIENT.REF_CVS_VICS_MATRIX_VW VM
WHERE VM.ACCESS_TO_VICS_BASE = 1
AND (VM.ACCESS_TO_VICS_DESTKOP_EMEA = 1 OR VM.ACCESS_TO_VICS_DESTKOP_AMCS = 1 OR VM.ACCESS_TO_VICS_DESTKOP_APAC = 1)
AND NOT EXISTS (SELECT 1 from CLIENT.FACTS F
WHERE F.BILLINGPERIOD = FRAMEWORK.CTL_Session_Parameters_PKG.Get_BillingPeriod()
AND F.BILLINGPERIOD = F.SERVICEPERIOD
AND F.INPUT_SOURCE IN ('CLIENT_MWP2_OPER','CLIENT_MWP2_COMP')
AND UPPER(F.CURRENT_USER) = UPPER(VM.SIGNUM))
UNION ALL
-- Other signums with VICS_Base =1, but without regional VICS_Desktop
SELECT '201904' AS ServiceMonth
, 'CLIENT' AS Source
, 'ID0000038' AS UniqueFileID
, 'ViCS_Apps' AS BillingDriver
, VM.SIGNUM AS "Signum-ID"
, 1 AS Quantity
, 'Yes' AS Billable
FROM CLIENT.REF_CVS_VICS_MATRIX_VW VM
WHERE VM.ACCESS_TO_VICS_BASE = 1
AND (VM.ACCESS_TO_VICS_DESTKOP_EMEA IS NULL OR VM.ACCESS_TO_VICS_DESTKOP_EMEA != 1)
AND (VM.ACCESS_TO_VICS_DESTKOP_AMCS IS NULL OR VM.ACCESS_TO_VICS_DESTKOP_AMCS != 1)
AND (VM.ACCESS_TO_VICS_DESTKOP_APAC IS NULL OR VM.ACCESS_TO_VICS_DESTKOP_APAC != 1)
Thank you
Here is an example to convert multiple rows of data into a single CLOB value delimited by newline. In the cursor part you may want to replace with your query.
create table test(c clob);
declare
lv_clob CLOB;
cursor c
is select rpad('*',level*2,' *')||chr(10) rec from dual connect by level <= 15;
c_rec varchar2(100);--Holds each record from above cursor in each iteration
begin
dbms_lob.createtemporary(lv_clob, TRUE);
open c;
loop
fetch c into c_rec;
exit when c%notfound;
dbms_lob.append(lv_clob, c_rec);
end loop;
insert into test values(lv_clob);
commit;
dbms_lob.freetemporary(lv_clob);
end;
select * from test;
Output:
C
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * * * * *
* * * * * * * * * * * * * * *
Related
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.)
I am trying to run a union all query in hive
select * from tabName where col1='val1' and col2 = 'val2' limit 10 union all select * from tabName where col1='val1' and col2 = 'val3' limit 10;
but i get
FAILED: ParseException line 1:105 missing EOF at 'union' near '10'
I also tried
( select * from tabName where col1='val1' and col2 = 'val2' limit 10 ) as a union all ( select * from tabName where col1='val1' and col2 = 'val3' limit 10 ) as b;
but i got
FAILED: ParseException line 1:109 missing EOF at 'as' near ')'
what am i doing wrong ?
Use select from subquery:
select * from
( select * from tabName where col1='val1' and col2 = 'val2' limit 10 ) a
union all
select * from
( select * from tabName where col1='val1' and col2 = 'val3' limit 10 ) b;
I offer another way using with clause:
with query1 as (
select *
from tabName
where col1 = 'val1' and col2 = 'val2'
limit 10
),
query2 as (
select *
from tabName
where col1 = 'val1' and col3 = 'val3'
limit 10
)
select * from query1
union all
select * from query2
i need to calculate metric values for 50 columns with same calculation pattern. i cannot use Union Query for all 50 columns as Source Qualifier in Informatica designer can hold upto 32767 characters.can anyone suggest ways TO achieve this ?
SELECT djm.jobcode|| '_' || djm.job_region || '_' ||
md.srvy_country_cd || '_' || djm.match_year AS srvy_label,
djm.match_year,
'NA' AS SRVY_PUBLISHER,
'Blend' AS cut,
'MI_UNIV_BLEND' AS srvy_name,
md.srvy_country_cd,
( md.base_25 ) * ( 1 + djm.adjustment ) * ( djm.geo_diff ) AS adj_base_25,
( md.base_50 ) * ( 1 + djm.adjustment ) * ( djm.geo_diff ) adj_base_50,
( md.base_75 ) * ( 1 + djm.adjustment ) * ( djm.geo_diff ) AS adj_base_75,
NULL AS adj_COMM_25,
NULL AS adj_COMM_50,
NULL AS adj_COMM_75,
djm.weight,
Sum(djm.weight) OVER (partition BY
djm.jobcode,djm.job_region,djm.match_year) sum_weight,
djm.weight*100 / Sum(djm.weight) OVER (partition BY
djm.jobcode,djm.job_region,djm.match_year) adj_weight
FROM md
INNER JOIN djm
ON djm.sk = md.sk
AND djm.jobcode ='1234'
AND djm.job_region ='USAB'
AND djm.match_year ='2016'
AND ( ( Nvl(md.base_25, 0) > 0 AND Nvl(md.base_50, 0) > 0
AND Nvl(md.base_75, 0) > 0 ) )
UNION
SELECT djm.jobcode|| '_' || djm.job_region || '_' || md.srvy_country_cd ||
'_' || djm.match_year AS srvy_label,
djm.match_year,
'NA' AS SRVY_PUBLISHER,
'Blend' AS cut,
'MI_UNIV_BLEND' AS srvy_name,
md.srvy_country_cd,
NULL AS adj_base_25,
NULL AS adj_base_50,
NULL AS adj_base_75,
( md.comm_25) * ( 1 + djm.adjustment ) * ( djm.geo_diff ) AS adj_COMM_25,
( md.comm_50) * ( 1 + djm.adjustment ) * ( djm.geo_diff ) AS adj_COMM_50,
( md.comm_75) * ( 1 + djm.adjustment ) * ( djm.geo_diff ) AS adj_COMM_75,
djm.weight,
Sum(djm.weight) OVER (partition BY
djm.jobcode,djm.job_region,djm.match_year)sum_weight,
djm.weight*100 / Sum(djm.weight) OVER (partition BY
djm.jobcode,djm.job_region,djm.match_year) adj_weight
FROM md
INNER JOIN djm
ON djm.sk = md.sk
AND djm.jobcode ='12178'
AND djm.job_region ='USAB'
AND djm.match_year ='2016'
AND ( ( Nvl(md.comm_25, 0) > 0 AND Nvl(md.comm_50, 0) > 0
AND Nvl(md.comm_75, 0) > 0 ) )
I'm not sure if you need 50 columns or 50 rows. This will give you 50 rows (I guess) if you put all 50 rows in the VALUES sub-select. (You could also use a table there)
SELECT djm.jobcode|| '_' || djm.job_region || '_' || md.srvy_country_cd || '_' || djm.match_year AS srvy_label,
djm.match_year,
'NA' AS SRVY_PUBLISHER,
'Blend' AS cut,
'MI_UNIV_BLEND' AS srvy_name,
md.srvy_country_cd,
( md.base_25 ) * ( 1 + djm.adjustment ) * ( djm.geo_diff ) AS adj_base_25,
( md.base_50 ) * ( 1 + djm.adjustment ) * ( djm.geo_diff ) adj_base_50,
( md.base_75 ) * ( 1 + djm.adjustment ) * ( djm.geo_diff ) AS adj_base_75,
NULL AS adj_COMM_25,
NULL AS adj_COMM_50,
NULL AS adj_COMM_75,
djm.weight,
Sum(djm.weight) OVER (partition BY djm.jobcode,djm.job_region,djm.match_year) sum_weight,
djm.weight*100 / Sum(djm.weight) OVER (partition BY djm.jobcode,djm.job_region,djm.match_year) adj_weight
FROM md
INNER JOIN djm
ON djm.sk = md.sk
AND ( ( Nvl(md.base_25, 0) > 0 AND Nvl(md.base_50, 0) > 0
AND Nvl(md.base_75, 0) > 0 ) )
INNER JOIN
TABLE( VALUES ( '1234', 'USAB', '2016')
, ( '12178', 'USAB', '2016')
-- etc etc
)
AS s(jobcode,job_region,match_year)
ON djm.jobcode = s.jobcode
AND djm.job_region = s.job_region
AND djm.match_year = s.match_year
If you do need 50 columns, you can always pivot them out with e.g. a SUM(CASE WHEN...)` for each column over the result set below
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
Is it practically possible to create a triangle of stars like this as below in SQL.I know that this could be done easily in any other programming language like C,C++,Java but want to know whether it is really possible with just SQL or PL/SQL.I tried working on it with dual table in Oracle but couldn't get through it.
* *
* * * *
* * * or * * *
Can someone please shed somelight if anyone knows about it.
The simplest approach would be something like this. You can get more sophisticated particularly if you want to build the equilateral triangle rather than the right triangle.
SQL> ed
Wrote file afiedt.buf
1 select rpad( '* ', level*2, '* ' )
2 from dual
3* connect by level <= 3
SQL> /
RPAD('*',LEVEL*2,'*')
--------------------------------------------------------------------------------
*
* *
* * *
select rpad('* ', level * 2, '* ')
from dual connect by
level <= 10
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
select rpad(' ',r*2,' ')||rpad('* ',l*2,'* ') k
from ( select level l,row_number() over(order by null) r
from dual
connect by level<=10
order by l desc)
* * * * * * * * * *
* * * * * * * * *
* * * * * * * *
* * * * * * *
* * * * * *
* * * * *
* * * *
* * *
* *
*
select rpad(' ',l*2,' ')||rpad('* ',r*2,'* ') k
from ( select level l,row_number() over(order by null) r
from dual
connect by level<=10
order by l desc)
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
select rpad(' ',l,' ')||rpad('* ',r*2,'* ') k
from ( select level l,row_number() over(order by null) r
from dual
connect by level<=10
order by l desc)
*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
Not sure what you are looking for exactly. Perhaps this?
select '*' from dual
union all select '**' from dual
union all select '***' from dual
Example
Here is the script to Get a perfect triangle or Pyramid in sql (tested in Microsoft Sql 2008)
declare #x int,#y int
select #x=5,#y=0
while #x>0
begin
print space(#x)+replicate('*',#y)+replicate('*',#y+1)
set #y=#y+1
set #x=#x-1
end
*
***
*****
*******
*********
you can get many more scripts and help at this link... it was helpful to me
Link:- sqlquerynscript
Try this..
declare #x int,#y int,#diff int
select #x=0,#y=10,#diff=2--diferrence between consecutive rows
while #x<#y
begin
if #x=0 and #diff<>1
print space((#y-#x)*#diff-1)+replicate('*',1)
else if(#diff%2=0)
print space((#y-#x)*#diff)+replicate('* ',#x+(#x*(#diff-1)))
else
print space((#y-#x)*#diff)+replicate('* ',#x+(#x*(#diff-1)))
select #x=#x+1
end
If all you want is the simple triangle, then you can do this:
SELECT '*' FROM table
UNION
SELECT '**' FROM table
UNION
SELECT '***' FROM table
declare #count int,#num int,#num1 int, #space int, #str varchar(50)
set #count = 5 set #num = 1
while(#num<=#count)
begin
set #num1 = 0 set #space = #count-#num
while (#num1<#num)
begin
if #str is null
set #str = '* '
else
set #str = #str+'* ' set #num1 = #num1+1
end
print (space(#space)+#str)
set #num = #num+1 set #str = null
end
[Equilateral Traingle] We can make a pyramid with Oracle SQL as follows.
select rpad(' ',5 -level) || rpad( '* ', level*2, '* ' )
from dual
connect by level <= 5;
** Here 5 is the number of lines.
Let us reverse it,
select rpad(' ',level) || rpad( '* ', 2*(5-level+1), '* ' )
from dual
connect by level <= 5;
declare #row int = 5,
#index int = 0,
#string nvarchar(5) =''
while #row > 0
begin
set #index = #row
while #index > 0
begin
set #string = '*' + #string
set #index = #index - 1
end
print #string
set #string = ''
set #row = #row - 1
end
*****
****
***
**
*
DECLARE #lclMaxLevel INT=5
DECLARE #lclPrintCount INT =0
WHILE #lclMaxLevel > 0
BEGIN
PRINT Space(#lclMaxLevel)
+ Replicate('*', #lclPrintCount+1)
SET #lclMaxLevel=#lclMaxLevel - 1
SET #lclPrintCount=#lclPrintCount + 1
END