How to get result from two queries in same output window? - oracle

I need output from the below two queries simultaneously in one output window.
QUERY 1
SELECT C.SERVICENAME, C.SERVICEID , B.SOAPIN, B.SOAPOUT, A.TIMESTAMP
FROM Schema1.LG_LOGENTRIES A, Schema1.LG_SOAPREQUESTS B, Schema1.CFG_SOAPSERVICES C
WHERE B.SERVICEID =C.SERVICEID AND
C.SERVICENAME <>'UploadAndPrepareDocumentEx1__sdweb_services_preload' AND
A.ID=B.LOGENTRYID AND B.TIMESTAMP BETWEEN TO_DATE('02/01/2018 11:55:00','dd/mm/yyyy hh24:mi:ss')
AND TO_DATE('02/01/2018 12:03:59','dd/mm/yyyy hh24:mi:ss') AND A.USERID IN (SELECT ID FROM Schema1.CFG_USERS
WHERE NAME=UPPER(TO_CHAR('CGBXGVSG')));
Query 2
SELECT B.JSONIN, B.JSONOUT, A.TIMESTAMP, B.EVENT_MESSAGE, A.PROCESSID, A.status, A.SERVERNAME
FROM Schema1.LG_LOGENTRIES A, Schema1.LG_EVENT B
WHERE B.EVENT_MESSAGE NOT IN ('getFileImage','submitBase64','loadDocumentToSign','getRefData') AND
A.ID=B.LOG_ENTRYID AND B.TIMESTAMP BETWEEN TO_DATE('31/12/2017 13:43:00','dd/mm/yyyy hh24:mi:ss')
AND TO_DATE('31/12/2017 13:53:59','dd/mm/yyyy hh24:mi:ss') AND A.USERID IN (SELECT ID FROM Schema1.CFG_USERS
WHERE NAME=UPPER(TO_CHAR('CTHX8Y2G')));

Run with F5 - you'll get both queries' output in the script panel.
I talk about how this differs here

UNION might be one option, but you'll have to
uniform both column lists (i.e. they have to return the same number of columns which have to be of the same data type), which means that you'd have to add certain NULL columns to both queries
include additional identifier so that you'd know which SELECT returned which values
If you wanted to have them side-by-side, huh, that's not that easy. Thinking loudly: you'd have to have a column that joins those values. Those SELECTs would be inline views. You'd use an aggregate function (such as MAX) along with a DECODE (or CASE) to select values from both queries. Shortly: too much pain.
Now, why do you want to do that? What's wrong with two separate windows, placed side by side?
[EDIT] Showing example of how UNION might look like
select c.servicename, c.serviceid, b.soapin, b.soapout, a.timestamp, to_char(null), to_char(null), to_char(null) , to_number(null), to_char(null), to_char(null)
from ... the rest of your 1st query
union
select null , null , null , null , a.timestamp, b.jsonin , b.jsonout , b.event_message, a.processid , a.status , a.servername
from ... the rest of your 2nd query

Related

How to add decode but also have count, group by and order by - not a group by expression

I'm rather new to Oracle. I'm trying to do a count of ports for a vendor/model. However, I only want ones with port_addr_status of 3 or 4. For some reason, I'm getting error
ORA-00979 not a group by expression
This is what I have so far. It works without the decode part, but I don't think the part with pi.port_addr.status in ('3','4') works without it. I'm open to working around that issue as well.
select
count(pi.port) as cnt, d.VENDOR, trim(d.model) as model,
decode(pi.PORT_ADDR_STATUS, '1', 'Unassigned', '2','Pending','3','In Service',
'4','Pending Disco', '5','Trouble', '6','Reserved',
'7','Reserved Capacity', pi.PORT_ADDR_STATUS)
from
table1 pi,
table2 d,
table3 c
where
pi.id = d.id and
pi.circuit_id = c.circuit_id
and pi.port_addr_status in ('3','4')
and (d.dslam_type_desc not in ('AGGREGATOR') or d.dslam_type_desc is null)
and d.DSLAM not like '%#%'
group by
d.VENDOR, d.model --, trim(d.model), pi.RACK, pi.SHELF, pi.SLOT, pi.PORT, pi.BROADBAND_CIRCUIT_ID, d.DSLAM,
order by
d.VENDOR asc, cnt desc
This is sample output:
1031 Adtran TA5000
10 Adtran TA1248V
3 Adtran TA1248
Since the decoded port type is not required in your output, just remove it from the select list. Group By should include everything in the select list except the aggregate functions. The below query should do the job:
select
count(pi.port) as cnt, d.VENDOR, trim(d.model) as model
from
table1 pi,
table2 d,
table3 c
where
pi.id = d.id and
pi.circuit_id = c.circuit_id
and pi.port_addr_status in ('3','4')
and (d.dslam_type_desc not in ('AGGREGATOR') or d.dslam_type_desc is null)
and d.DSLAM not like '%#%'
group by
d.VENDOR, trim(d.model)
order by
d.VENDOR asc, cnt desc
Note that the filter down to specific port types is achieved here:
and pi.port_addr_status in ('3','4')
in the where clause - the decode statement in your original query did nothing to solve your requirements and was the direct cause of the error. In a basic aggregate query like this, group by should have every item that is in the select list that is not an aggregate function.
You might use decode statement in the select list with an aggregation function preferably max as
max( decode(pi.PORT_ADDR_STATUS, '1', 'Unassigned', '2','Pending', .... )
The reason you're getting that error is:
when using a GROUP BY clause you are asking the DBMS to give you a single row corresponding to your GROUP BY list
in your case, you are asking for one row per (Vendor, Model) combination
since each of these rows represents possibly many "underlying" rows (say, e.g. 5 rows for Vendor=A and Model=B), the only other fields you can have in the select list must be aggregates (that's why the "count" field works, it counts the rows, i.e. it can take many row values and return a single value)
the DECODE function is not an aggregate function - it can't "collapse" multiple values into one value (like, say, MAX() can)
It looks to me as if your DECODE function returns strings, so I recommend you aggregate the strings with the LISTAGG function (so if your 5 rows have values of 'asdf', 'fdsa', 'qwer', 'rewq', and 'zxcv' the LISTAGG function would return a single string: 'asdf,fdsa,qwer,rewq,zxcv')
So you would replace your DECODE(...) call with, e.g. LISTAGG(DECODE(...), ',')
Reference for LISTAGG function: https://docs.oracle.com/cd/E11882_01/server.112/e41084/functions089.htm#SQLRF30030

How to get dummy rows using SQL Query?

I have a requirement where i have to fetch some rows based on a condition and apart from that 2 more rows should be there in output one will be * and other will be a blank row. I am using the approach of Union to club that 2 extra rows.
Query :
SELECT '' as PROMO_GRP_CD , '' as PROMO_GRP_DESC, '' as PROMO_GRP_ALT_DESC
from PROMO_GROUP
UNION
SELECT '*' as PROMO_GRP_CD , 'All' as PROMO_GRP_DESC, 'Tous' as PROMO_GRP_ALT_DESC
from PROMO_GROUP
UNION
SELECT PROMO_GRP_CD,PROMO_GRP_DESC,PROMO_GRP_ALT_DESC from PROMO_GROUP
where ACC_TYPE = '*' and ACC_SUB_TYPE = '*' and SUBMARKET = '*'
In above Query first 2 selects from Table PROMO_GROUP gives me a blank row and a row with * value and below that i have normal select to retrieve data from Table PROMO_GROUP based on condition.
Is there any other optimum way through which i can achieve this ?
If you want to do it in query only, this is the best way. You should remove the from promo_group part from first two queries
But if you can, you should handle this in your code instead of your query
You need to create each dummy row using a SELECT clause that has no FROM clause (or in Oracle, from the special DUAL table, so it produces exactly one row), and UNION those two with the actual query. Like this:
SELECT '' as PROMO_GRP_CD , '' as PROMO_GRP_DESC, '' as PROMO_GRP_ALT_DESC FROM DUAL
UNION
SELECT '*' as PROMO_GRP_CD , 'All' as PROMO_GRP_DESC, 'Tous' as PROMO_GRP_ALT_DESC FROM DUAL
UNION
SELECT PROMO_GRP_CD,PROMO_GRP_DESC,PROMO_GRP_ALT_DESC from PROMO_GROUP
WHERE ACC_TYPE = '*' and ACC_SUB_TYPE = '*' and SUBMARKET = '*'
You can append the returned result with your two records (adding two element to the array). The result will be the same and you won't have the overhead of the UNION.
Of course you didn't specify what language you are using to run the query through. I am presuming your language will allow this.

ORA-000932 When joining an xmltype to a varchar field

a little backstory, i have a comma delimited column in a database, that i have tried to convert into a many to many junction table, so instead of having
ID REPORT
1 5,6,7
i would see
ID REPORT
1 5
1 6
1 7
the query below does just that, and seems to work correctly,
with t as (select id,hqcat from report)
SELECT id, EXTRACT(column_value,'/e/text()') hqcat from t x,
TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE('<ROW><e>'||REPLACE(hqcat,',','</e><e>')||'</e></ROW>'),'//e')))
however when i try to join it to my lookup table by hqcat, i get a ORA-00932 error about inconstant data types, please help me, how do i change my original query to make it work with other tables and joins?
here is the join causing the error:
select *
from BIN03 a11
join ( with t as (select id,hqcat from report)
SELECT id, EXTRACT(column_value,'/e/text()') hqcat from t x,
TABLE(XMLSEQUENCE(EXTRACT(XMLTYPE('<ROW><e>'||REPLACE(hqcat,',','</e><e>')||'</e></ROW>'),'//e')))) a12
on (a11.CODE = a12.HQCAT);
Thank you!
i've also tried to create my new "many to many" view as so:
WITH TAB AS
( (select id ID, hqcat STR from report))
SELECT ID as ID,
REGEXP_SUBSTR (STR, '[^,]+', 1, LEVEL) HQCAT FROM TAB
CONNECT BY LEVEL <= (regexp_count(str,',') + 1);
but this just reduces query speeds by 1000's.....
The (deprecated) extract function returns an XMLType, not a varchar2. You can cast it to the type you want, either in the inline view:
cast(EXTRACT(column_value,'/e/text()') as varchar2(3))
or when comparing the value:
a11.CODE = cast(a12.HQCAT as varchar2(3))
I've guessed the variable size you need, obviously, you might need it to be different. You could also use the XMLType getStringVal() function as shown below.
It seems little odd to mix an old-style cross join with a comma in the inline view's from clause, with ANSI joins in the rest, and you can get odd (or hard to debug, anyway) results doing that. You could also use another CTE for clarity:
with t as (select id, hqcat from report),
a12 as (
select id, extract(column_value,'/e/text()').getstringval() hqcat
from t
cross join table(xmlsequence(extract(xmltype('<ROW><e>'||
replace(hqcat,',','</e><e>')||'</e></ROW>'),'//e')))
)
select *
from a12
join bin03 a11 on a11.code = a12.hqcat;

Print different sets of data from different tables in one SQR

I have a requirement where in if a PO_ID range is given then I need to do the following:
If a PO_ID from the PO_ID range is present in PS_DISTRIB_LINE then print PO_ID and Voucher ID and if not then print PI_ID and PO_DT from PS_PO_HDR.
How to achieve this.
Union is not working and I am not able to use break logic because if data is present in PS_DISTRIB_LINE then I am printing Sum of PO_AMT Total below the PO_IDs but in other case i am not.
UNION is possible in SQR, but the syntax is difficult.
You will need to put the UNION in parenthesis and make sure to put commas after the selected items. In the example below, I put commas after a.name, a.first_name, and a.last_name. Repeat this for b.name, b.first_name, and b.last_name.
I've run this example and this works for me:
begin-SELECT
employee_name.name
employee_name.first_name
employee_name.last_name
Show 'employee_name.name: ' &employee_name.name
Show 'employee_name.first_name: ' &employee_name.first_name
Show 'employee_name.last_name: ' &employee_name.last_name
from
(
select
a.name,
a.first_name,
a.last_name
from ps_names a
where name_type = 'PRI'
and emplid = '000000001'
union
select
b.name,
b.first_name,
b.last_name
from ps_personal_data b
where emplid = '000000001'
) employee_name
end-SELECT

NOT IN query... odd results

I need a list of users in one database that are not listed as the new_user_id in another. There are 112,815 matching users in both databases; user_id is the key in all queries tables.
Query #1 works, and gives me 111,327 users who are NOT referenced as a new_user_Id. But it requires querying the same data twice.
-- 111,327 GSU users are NOT listed as a CSS new user
-- 1,488 GSU users ARE listed as a new user in CSS
--
select count(gup.user_id)
from gsu.user_profile gup
join (select cud.user_id, cud.new_user_id, cud.user_type_code
from css.user_desc cud) cudsubq
on gup.user_id = cudsubq.user_id
where gup.user_id not in (select cud.new_user_id
from css.user_desc cud
where cud.new_user_id is not null);
Query #2 would be perfect... and I'm actually surprised that it's syntactically accepted. But it gives me a result that makes no sense.
-- This gives me 1,505 users... I've checked, and they are not
-- referenced as new_user_ids in CSS, but I don't know why the ones
-- that were excluded were excluded.
--
-- Where are the missing 109,822, and whatexcluded them?
--
select count(gup.user_id)
from gsu.user_profile gup
join (select cud.user_id, cud.new_user_id, cud.user_type_code
from css.user_desc cud) cudsubq
on gup.user_id = cudsubq.user_id
where gup.user_id not in (cudsubq.new_user_id);
What exactly is the where clause in the second query doing, and why is it excluding 109,822 records from the results?
Note The above query is a simplification of what I'm really after. There are other/better ways to do the above queries... they're just representative of the part of the query that's giving me problems.
Read this: http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:442029737684
For what I understand, your cudsubq.new_user_id can be NULL even though both tables are joined by user_id, so, you won't get results using the NOT IN operator when the subset contains NULL values . Consider the example in the article:
select * from dual where dummy not in ( NULL )
This returns no records. Try using the NOT EXISTS operator or just another kind of join. Here is a good source: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
And what you need is the fourth example:
SELECT COUNT(descr.user_id)
FROM
user_profile prof
LEFT OUTER JOIN user_desc descr
ON prof.user_id = descr.user_id
WHERE descr.new_user_id IS NULL
OR descr.new_user_id != prof.user_id
Second query is semantically different. In this case
where gup.user_id not in (cudsubq.new_user_id)
cudsubq.new_user_id is treated as expression (doc: IN condition), not as a subquery, thus the whole clause is basically equivalent to
where gup.user_id != cudsubq.new_user_id
So, in your first query, you're literally asking "show me all users in GUP, who also have entries in CSS and their GUP.ID is not matching ANY NOT NULL NEW_ID in CSS ".
However, the second query is "show me all users in GUP, who also have entries in CSS and their GUP.ID is not equal to their RESPECTIVE NULLABLE (no is not null clause, remember?) CSS.NEW_ID value".
And any (not) in (or equality/inequality) checks with nulls don't actually work.
12:07:54 SYSTEM#oars_sandbox> select * from dual where 1 not in (null, 2, 3, 4);
no rows selected
Elapsed: 00:00:00.00
This is where you lose your rows. I would probably rewrite your second query's where clause as
where cudsubq.new_user_id is null, assuming that non-matching users have null new_user_id.
Your second select compares gup.user_id with cud.new_user_id on current joining record. You can rewrite the query to get the same result
select count(gup.user_id)
from gsu.user_profile gup
join (select cud.user_id, cud.new_user_id, cud.user_type_code
from css.user_desc cud) cudsubq
on gup.user_id = cudsubq.user_id
where gup.user_id != cud.new_user_id or cud.new_user_id is null;
You mentioned you compare list of user in one database with a list of users in another. So you need to query data twice and you don't query the same data. Maybe you can use "minus" operator to avoid using "in"
select count(gup.user_id)
from gsu.user_profile gup
join (select cud.user_id from css.user_desc cud
minus
select cud.new_user_id from css.user_desc cud) cudsubq
on gup.user_id = cudsubq.user_id;
You want new_user_id's from table gup that don't match any new_user_id on table cud, right? It sounds like a job for a left join:
SELECT count(gup.user_id)
FROM gsu.user_profile gup LEFT JOIN css.user_desc cud
ON gup.user_id = cud.new_user_id
WHERE cud.new_user_id is NULL
The join keeps all rows of gup, matching them with a new_user_id if possible. The WHERE condition keeps only the rows that have no matching row in cud.
(Apologies if you know this already and you're only interested in the behavior of the not in query)

Resources