I have the below code to show what I am "trying" to accomplish in a stored procedure:
select * from
(
select to_char(sum(aa.amount))
from additional_amount aa, status st
where aa.int_tran_id = st.int_tran_id
and st.stage in ('ACHPayment_Confirmed')
and aa.entry_timestamp > (
select to_date(trunc(last_day(add_months(sysdate,-1))+1), 'DD-MON-RR') AS "day 1"
from dual
)
)
UNION ALL
(
select distinct it.debit_acct as "debit_accounts"
from internal_transactions it
where it.debit_acct IN ( select texe_cnasupro
from service.kndtexe, service.kndtctc
where texe_cncclipu = tctc_cncclipu
and tctc_cntipcli = 'C'
)
)
union all
(select distinct it.credit_acct as "credit_account"
from internal_transactions it
where it.credit_acct IN (select texe_cnasupro
from service.kndtexe, service.kndtctc
where texe_cncclipu = tctc_cncclipu
and tctc_cntipcli = 'C'
)
)
;
Output:
TO_CHAR(SUM(AA.AMOUNT))
----------------------------------------
130250292.22
6710654504
0000050334
2535814905
0007049560
5 rows selected
The top row of the output is what I need in the SP as output based on the below two queries which I am guessing needs to be sub-queried against the top select statement.
The top select is to select the sum of the amount a table with a join against another table for filtering (output:130250292.22).
The second and third selects is actually to check that the accounts in the internal_transactions table are signed up for the corresponding two tables in the service db which is a different db on the same server(owned by the same application).
The tables in the "service" db do not have the same common primary keys as in the first select which is against the same database.
Thank you for your help!
I don't understand your question, but I do know you can simplify this bit:
to_date(trunc(last_day(add_months(sysdate,-1))+1), 'DD-MON-RR') AS "day 1"
to this
trunc (sysdate, 'mm')
and you don't need a SELECT from DUAL to do that either.
and aa.entry_timestamp > trunc (sysdate, 'mm')
Related
I have the below Query. My Expected output would be as below. Please help me make changes to the Query
select
ID,TERM,
case
when TERM like '____1_' then
function_toget_hrs(ID, TERM,sysdate) else null
end fall_hours,
case
when TERM like '____2_' then
function_toget_hrs(ID, TERM,sysdate) else null
end winter_hours
from TABLE_TERM
where ID='12087762'
Expecting one row for each ID. Please help me the ways
Pivoting is what you need:
WITH TABLE_TERM AS
(
SELECT 12087762 AS ID, '202110____1_' AS term, 12 AS func FROM dual UNION ALL
SELECT 12087762 AS ID, '202120____2_' AS term, 16 FROM dual UNION ALL
SELECT 12087762 AS ID, '202140____1_' AS term, 0 FROM dual
)
SELECT *
FROM (SELECT ID
, DECODE(SUBSTR(term,-6),'____1_','fall_hours','winter_hours') AS hrs
, func --function_toget_hrs(ID, TERM,sysdate) for test purposes
FROM TABLE_TERM
WHERE ID = '12087762'
)
PIVOT (SUM(func) FOR hrs IN ('fall_hours','winter_hours'));
I have following table structure: http://sqlfiddle.com/#!4/952e7/1
Now I am looking for a solution for the following problem:
Given an input data-time set (see below). And the SQL statement should return all of business IDs with a given business name, where every single date-times of the input set are either present in the ORDERS table or an additional function's statement is true (these both conditions are separately to be checked for each input date-time).
An example how the input date-time dataset looks like:
WITH DATES_TO_CHECK(DATETIME) AS(SELECT DATE '2021-01-03' FROM DUAL UNION ALL SELECT DATE '2020-04-08' FROM DUAL UNION ALL SELECT DATE '2020-05-07' FROM DUAL)
To be simple, the "additional function" should be a simple random number (if greather than 0.5 than true otherwise false, so the check is dbms_random.value > 0.5).
For one given date time it would look like:
SELECT BN.NAME, BD.ID
FROM BUSINESS_DATA BD, BUSINESS_NAME BN
WHERE BD.NAME_ID=BN.ID AND
BN.NAME='B1' AND
(TO_DATE('2021-01-03', 'YYYY-MM-DD') IN (SELECT OD.ORDERDATE FROM ORDERS OD WHERE OD.BUSINESS_ID=BD.ID)
OR dbms_random.value > 0.5)
ORDER BY BD.ID
Please help me, how this solution can be applied to the input date-time rowset above AND the specified name.
I don't any difference with the question you just deleted
This is the list of businesses named B1 and for which the number of order dates that match date input dates is equal to the number of input dates or dbms_random.value > 0.5
see SQL Fiddle
WITH DATES_TO_CHECK(DATETIME) AS(
SELECT DATE '2021-01-03' FROM DUAL
UNION ALL SELECT DATE '2020-04-08' fROM DUAL
UNION ALL SELECT DATE '2020-05-07' fROM DUAL
),
businesses_that_match as (
select
od.BUSINESS_ID, count(distinct OD.ORDERDATE)
from DATES_TO_CHECK dtc
left join ORDERS od on OD.ORDERDATE = dtc.datetime
group by od.BUSINESS_ID
having count(distinct OD.ORDERDATE) = (select count(distinct DATETIME) from DATES_TO_CHECK)
)
SELECT
BN.NAME, BD.ID
FROM BUSINESS_DATA BD
inner join BUSINESS_NAME BN on BD.NAME_ID=BN.ID
left join businesses_that_match btm on btm.BUSINESS_ID = bd.id
where bn.name = 'B1'
AND (btm.BUSINESS_ID is not null
OR dbms_random.value > 0.5
)
I am approaching this issue from a non DBA perspective, as in I do not have permissions to create new tables for the database. I am trying to work around this by using a subquery in Oracle kind of like this sudo code:
With temptable as ('col1name', 'col2name', 1,'a',2,'b')
Select * from temptable where col1name = 1
With the temptable looking like
Col1name | Col2name
1 a
2 b
And the output being row 1. I know it is not the easiest way to do it, but it is all I can think of to accomplish my task until I can get the admin to approve a new table. I have searched a lot but I can't find an answer. Is there a simple way to define temporary table data like this?
I would just do this as:
with temptable as (
select 1 as col1name, 'a' col2name from dual union all
select 2, 'b' from dual
)
Select *
from temptable
where col1name = 1;
As an alternative to a CTE (common table expresssion) as suggested by Gordon, you can also use a query as an old-school inline view.
For example:
SELECT tt.col1name
, tt.col2name
FROM ( SELECT 1 AS col1name, 'a' AS col2name FROM DUAL
UNION ALL SELECT 2, 'b' FROM DUAL
UNION ALL SELECT 3, 'c' FROM DUAL
) tt
WHERE tt.col1name = 1
ORDER
BY tt.col1name
Lets assume 'table1' has three columns:
'key',
'singleID',
'multipleIDs'
Rows would be like:
1,'8736', '1234;6754;9785;6749'
2,'7446', '9959;7758;6485;9264'
To search for all rows which have an id either in 'singleID' or as part of
the concatenated IDs in the 'multipleIDs' I would:
select key from table1 where
singleID = '8888' or multipleIDs like '%8888%';
When searching not only for one ID (8888) like in this statement but for 100 it would be necessary to repeate the where clause 100 times with different id like:
select key from table1 where
singleID = '8888' or multipleIDs like '%8888%' or
singleID = '9999' or multipleIDs like '%9999%' or
....;
The IDs to search for are taken dynamically from another query like
select id from table2;
The query shall
be created dynamically since the number of IDs might vary.
Like this the SQL statement would become quite long.
Is there a nice and short way to express that in Oracle SQL? PLSQL perhaps?
Something like this?
This is the test version:
with sv_qry
as
(
SELECT trim(regexp_substr(search_values, '[^,]+', 1, LEVEL)) val
FROM (select '1234,7446' as search_values
from dual
)
CONNECT BY LEVEL <= regexp_count(search_values, ',')+1
)
, table1_qry
as
(select 1 as id,'8736' as single_id, '1234;6754;9785;6749' as multiple_id from dual
union all
select 2,'7446' as single_id, '9959;7758;6485;9264' as multiple_id from dual
)
select *
from table1_qry
inner join
sv_qry
on single_id = val or multiple_id like '%'||val||'%'
And this would be with a table called table1:
with sv_qry
as
(
SELECT trim(regexp_substr(search_values, '[^,]+', 1, LEVEL)) val
FROM (select '1234,7446' as search_values
from dual
)
CONNECT BY LEVEL <= regexp_count(search_values, ',')+1
)
select *
from table1
inner join
sv_qry
on single_id = val or multiple_id like '%'||val||'%'
Partial credit goes here:
Splitting string into multiple rows in Oracle
You can express the query like this :
select key
from table1 a
join ( select id from table2 where id in ('yyyy','xxxx','zzzz',...) b
on a.singleId = b.id or a.multipleID like '%'||b.id||'%';
I have a script that extracts transactions and their details from a database. But my users complain that the file size being generated is too large, and so they asked for certain transactions to be just summed up/consolidated instead if they are of a certain classification, say Checking Accounts. That means there should only be one line in the result set named "Checking" which contains the sum of all transactions under Checking Accounts. Is there a way for an SQL script to go like:
CASE
WHEN Acct_class = 'Checking'
then sum(tran_amount)
ELSE tran_amount
END
I already have the proper GROUP BY and ORDER BY statements, but I can't seem to get my desired output. There is still more than one "Checking" line in the result set. Any ideas would be very much appreciated.
Try This,
Select sum(tran_amount) From tran_amount Where Acct_class = 'Checking'
You can try to achieve this using UNION ALL
SELECT tran_amount, .... FROM table WHERE NOT Acct_class = 'Checking'
UNION ALL
SELECT SUM(tran_amount), .... FROM table WHERE Acct_class = 'Checking' GROUP BY Acct_class, ...;
hi you can try below sql
select account_class,
case when account_class = 'saving' then listagg(trans_detail, ',') within group (order by emp_name) -- will give you all details transactions
when account_class = 'checking' then to_char(sum(trans_detail)) -- will give you only sum of transactions
end as trans_det from emp group by account_class;
Or, if your desired output is getting either the sum, either the actual column value based on another column value, the solution would be to use an analytical function to get the sum together with the actual value:
select
decode(acct_class, 'Checking', tran_amount_sum, tran_amount)
from (
select
sum(tran_amount) over (partition by acct_class) as tran_amount_sum,
tran_amount,
acct_class
from
YOUR_TABLE
)
You can try something like the following, by keeping single rows for some classes, and aggregating for some others:
with test (id, class, amount) as
(
select 1, 'a' , 100 from dual union all
select 2, 'a' , 100 from dual union all
select 3, 'Checking', 100 from dual union all
select 4, 'Checking', 100 from dual union all
select 5, 'c' , 100 from dual union all
select 6, 'c' , 100 from dual union all
select 7, 'c' , 100 from dual union all
select 8, 'd' , 100 from dual
)
select sum(amount), class
from test
group by case
when class = 'Checking' then null /* aggregates elements of class 'b' */
else id /* keeps elements of other classes not aggregated */
end,
class