Need to understand the query in oracle - oracle

SELECT DISTINCT 'update loc_final_2 set county = ''' || TRIM(upper(county) ) || '''
where city = '''
|| TRIM(upper(city) ) || ''' and state = ''' || TRIM(upper(state) ) || ''';'
FROM audtr_rgn_assgnmnts;
commit
can somebody tell me what the above query does. There's a table called loc_final_2 and another one called audtr_rgn_assgnmnts. I don't understand what the query is doing and I need to improve this query. But before that I have to understand what it is doing. I also need to know what commit is doing at the end.

The query is trying to generate multiple update statements for the table loc_final_2 using the values from audtr_rgn_assgnmnts.
I'm not sure why the commit exists there as the queries are not being executed.
If at all the intention of the original coder of the query was to run multiple updates, then I would say it's a wrong approach. A single update / MERGE like this would be more straightforward and performant.
UPDATE loc_final_2 l
SET
county = (
SELECT upper(TRIM(county) ) --Add MIN/MAX if there are multiple rows
FROM audtr_rgn_assgnmnts a
WHERE l.city = upper(TRIM(a.city) ) AND l.state = upper(TRIM(a.state) )
);
MERGE INTO loc_final_2 t USING audtr_rgn_assgnmnts s ON (
l.city = upper(TRIM(a.city) ) AND l.state = upper(TRIM(a.state) )
)
WHEN MATCHED THEN UPDATE SET t.county = UPPER(TRIM(s.county));
If there are multiple rows, you would need to do a select distinct in the USING
MERGE INTO loc_final_2 t USING (
SELECT DISTINCT city,
state,
upper(TRIM(s.county) ) AS county
FROM audtr_rgn_assgnmnts
)
s ON (
l.city = upper(TRIM(a.city) ) AND l.state = upper(TRIM(a.state) )
)
WHEN MATCHED THEN UPDATE SET t.county = s.county;
EDIT :
what is the 3-single quote doing in the query
A literal quote in Oracle needs to be escaped using another single quote.
So, If your final query needs to have something like a='b' , the expression generating that string should be a=||'''b||''' one the quite itself, one quote to escape that quote, other the part of concatenation.
because min/max can be used only for numbers, right?
MAX and MIN can be used on strings. Here I said you may use it to avoid duplicate values for same county returned from the inner query. DISTINCT is also an option if you don't want to use MIN/MAX.

Related

Iterate a select query for a set of varchar2 in oracle

I have a below select query
select * from BUSINESS_T
where store_code = '075'
and item_no in
(
select item_no from BUSINESS_T a
where store_code = '075'
and exists
(
select * from BUSINESS_T
where store_code = a.store_code
and item_no = a.item_no
and
(
VALID_FROM_DTIME between a.VALID_FROM_DTIME and a.VALID_TO_DTIME
or VALID_TO_DTIME between a.VALID_FROM_DTIME and a.VALID_TO_DTIME
or (VALID_FROM_DTIME > a.VALID_FROM_DTIME and a.VALID_TO_DTIME is null)
or (VALID_FROM_DTIME < a.VALID_FROM_DTIME and VALID_TO_DTIME is null)
)
and del_dtime is null
and not
(
a.rowid = rowid
)
)
)
order by item_no, VALID_FROM_DTIME
Need to run it for a array of store numbers {'071','072','073','074','075','076'}
This array should defined inside the query itself.
Nearly 400+ fixed store numbers are there. The above query has to be run for each store, at a time for one store , To find the overlapping in that particular store
If i run by passing the collection of store numbers, there is a chance items are common in many stores that will cause a problem.
You can still use in if you modify the first subquery to get return the store/item pairs, which handles the common items:
select * from BUSINESS_T
where (store_code, item_no) in
(
select store_code, item_no from BUSINESS_T a
where store_code in ('071','072','073','074','075','076')
...
Or with a collection:
select * from BUSINESS_T
where (store_code, item_no) in
(
select store_code, item_no from BUSINESS_T a
where store_code member of sys.dbms_debug_vc2coll('071','072','073','074','075','076')
...
db<>fiddle with very simple demo of the idea.
Use in:
select *
from business_t
where
class_unit_code in ('071', '072', '073', '074', '075', '076')
and b_type = 'CASH_AND_CARRY'
and delete_date is null
For this specific sequence of string values, we might try to shorten the predicate using a regex (although this is probably less efficient):
regexp_like(class_unit_code, '^07[1-6]$')
Or if the string always contains numeric values, we can convert and use a range comparison (which also is not as efficient as the first option - in that case, the column should have been created with a numeric datatype to start with):
to_number(class_unit_code) between 71 and 76

how to get the '' for each string in a listagg?

I have the following query :
SELECT
ix.dt AS DT,
ix.UDBENCH_UDIDX AS UDFO,
' .' || REPLACE(REPLACE( ix.UDBENCH_UDIDX,' ',''),'IS','') AS PF_TICKER,
i.szbez AS PORTFOLIO_NAME,
ix.rm_generic_inst_type_l1,
ix.rm_generic_inst_type_l2,
ix.scd_sec_type,
m.ud_isin AS SECURITY_ID,
'%' AS POS_TYPE,
ix.sec_weight AS QUANTITY,
ix.sec_ccy,
ix.sec_price AS MKT_PRICE,
'' AS COST_PX,
'' AS POSITION_VALUE_AC,
'' AS POSITION_VALUE_FC,
m.ud_sedol AS UD_SEDOL,
m.ud_bbgid AS UD_ID_BB_UNIQUE,
m.ud_cusip AS UD_CUSIP,
m.ud_bbgid AS UD_BBGID,
m.inst_name AS INST_NAME,
ix.idas AS IDAS,
m.ud_scd_securityid AS UD_SCD_SECURITYID
FROM XXXX ix
INNER JOIN XXXXR i ON (i.udidx = ix.UDBENCH_UDIDX),
XXXXX m
WHERE ix.dt >= to_date(sdt_start,'DD.MM.YYYY')
AND ix.dt <= to_date(sdt_end,'DD.MM.YYYY')
AND ix.UDBENCH_UDIDX IN (select listagg( udfo,',') within group(ORDER BY udfo)
from XXXXX where pf_ticker is null )
AND i.szbez LIKE '%DFLT%'
AND ix.idas = m.idas;
I would like the part :
AND ix.UDBENCH_UDIDX IN (select listagg( udfo,',') within group(ORDER
BY udfo)
from XXXXX where pf_ticker is null )
Equivalent to : ix.UDBENCH_UDIDX IN ('blal','bll',blc') but it shows ix.UDBENCH_UDIDX IN (blal,bll,blc) and the result of my query is an empty table, do you know how to set listagg to have this result ( 'blal','bll',blc' instead of blal,bll,blc)?
Thanks
The IN operator doesn't work like that. You'd be comparing the UDBENCH_UDIDX values with a single string containing all udfo values, not all of the individual values of that column.
You can just use a subquery without the listagg():
AND ix.UDBENCH_UDIDX IN (select udfo from XXXXX where pf_ticker is null)
Or you can join to that table instead of using a subquery at all; something like:
FROM XXXX ix
INNER JOIN XXXXR i ON (i.udidx = ix.UDBENCH_UDIDX)
INNER JOIN XXXXX m ON (m.udfo = ix.UDBENCH_UDIDX)
WHERE ix.dt >= to_date(sdt_start,'DD.MM.YYYY')
AND ix.dt <= to_date(sdt_end,'DD.MM.YYYY')
AND i.szbez LIKE '%DFLT%'
AND ix.idas = m.idas
AND m.pf_ticker is null;
... assuming the old-style join to XXXXX m is supposed to be getting the data related to the subquery you're doing - it's hard to tell with obfuscated names. (It's not a good idea to mix old and new style joins anyway; or to use old-style joins at all). It's possible you might want that to be an outer join, or the driving table, or something else - again can't infer that from the information provided.
If you already had a set of string literals to look for then you would do something like:
IN ('val1', 'val2', 'val3')
but you don't have string literals, you have string values from a table, which are not the same. You don't need to, and shouldn't, enclose those column values in single quotes within the query. The single quotes denote a literal value which is to be treated as a string; the values in the column are already strings.
You can actually do what you asked:
select '''' || listagg(udfo, ''',''') within group (order by udfo) || '''' from ...
which would give you a comma-separated list of quoted values from your table (or an empty string, which is the same as null, if there are no matching rows. If you were generating a statement to run later then that might make some sense, but that isn't the case here.

DAX pick a value from tied resultset

i need help with the following dax statement.
Situation:
I have 2 tables. One table contains sell data with articleIDs, dateIDs and sell prices, another table contains stock movements data with articleIDs, dateIDs and purchase prices. According to the dateID i want to write the purchase prices into the first table using a calculated column because i need the prices for every row.
Example:
Table1 t1
t1.articleID = 123; t1.dateID = 20160905; t1.sellPrice = 62,55; t1.purchasePrice = My DAX Statement
Table2 t2
t2.articleID = 123; t2.dateID = 20160905; t2.purchasePrice = 37,07
t2.articleID = 123; t2.dateID = 20160905; t2.purchasePrice = 37,07
t2.articleID = 123; t2.dateID = 20160906; t2.purchasePrice = 37,07
t2.articleID = 456; t2.dateID = 20160905; t2.purchasePrice = 12,15
My DAX Statement:
= CALCULATE (
VALUES (t2[purchasePrice]);
TOPN (
1;
FILTER(FILTER(t2; t2[articleID] = t1[articleID]); t2[dateID] <= t1[dateID]); t2[dateID]; DESC
)
)
With my DAX Statement i get the following error:
A table of multiple values was supplied where a single value was expected.
It is normal that i have more than one row matching in the table 2.
Actually I just want the price of any of them on the corresponding dateID, even if they are tied. So i used the TOPN function with the value 1 and sorted by date but the error still remains. Is there a way to fix my DAX Statement to achieve this?
Create a calculated column in T1 and use this expression:
purchasePrice =
CALCULATE (
MAX ( T2[purchasePrice] ),
FILTER ( T2, T1[ArticleID] = T2[articleID] && T1[DateID] = T2[dateID] )
)
Note I use comma to separate passed arguments to the functions but I see in your expression you used semicolon. Change it to match your system list separator.
It is not tested but should work. Let me know if it works for you.

summing values from one table into another table

I'm an SQL newbie using VB6/Access 2000 and am trying to get a query which puts the sum of values from a table into another table.
VB6 does the job, but it's so slow.
I searched and tried in Access many times, just got lost with keywords IN, ON, (INNER) JOIN, each time getting a different error.
The core code should be as follows:
update t1
set t1.value = sum(t2.value)
where
val(t2.code)>89
and
t2.date=t1.date
t1.date is a date, no duplicates
t2.code is a variable string like '0081', '090'
values are single precision
After further searching i found a similar question here ( http://goo.gl/uqlw0U ) and tried that:
UPDATE t1
SET t1.value =
(
SELECT
SUM(t2.value)
FROM spese
WHERE
t1.date=t2.date
AND
val(t2.code)>89
)
but Access just says "updatable query needed" -- what does that mean?
Try this:
UPDATE t1
SET t1.value = SUM(t2.value)
FROM t1, t2
WHERE
val(t2.code)>89
AND
t2.date=t1.date

ORA-01791 Pl-Sql error

hi guy i have a query that give me the followin error:
ORA-01791: not a SELECTed expression
this is the select expresison , please can you tell me why ?
declare
freqLettura varchar2(64);
billingcy varchar2(64);
begin
freqLettura := null;
billingcy := null;
for rec in ( select distinct(fn_get_facilityid(z.uidfacility) ) as a, 1 as b
from facilityhistory z,
locality l ,
plant p ,
ztmp_sam_tb_sdv zsdv ,
ztmp_sam_tb_plantcode zplant ,
sam_tb_ca_pdr sam,
meterhistory mh,
meter m ,
meterclass mc
where
Z.UIDLOCALITY = L.UIDLOCALITY and
p.UIDPLANT = L.UIDPLANT and
z.uidaccount = zsdv.uidaccount and
p.plantcode = zplant.plantcode and
sam.uidfacility = z.uidfacility and
z.stoptime is null and
sam.status = 'U' and
mh.uidfacility = z.uidfacility and
mh.uidmeter = m.uidmeter and
m.uidmeterclass = mc.uidmeterclass and
(billingcy is null or p.UIDBILLINGCYCLE = billingcy )
AND
(
(
(freqLettura = 'G') AND ( mh.corrmeterid is not null and mh.stoptime is null and mc.maxflowmeter >= SAM_FN_GET_PARAMETER_FLOAT('MAXFLOWMET_DETT_GIORN'))
)
OR
(
nvl(freqLettura,'nullo') <> 'G' AND (freqLettura is null or sam.readfrequency = freqLettura)
)
) and ROWNUM = 1 order by sam.stoptime, sam.uidsamtbpdr desc ) loop
begin
insert into ztmp_sam_tb_elab_pdr (facilityid, uidbatchrequest) VALUES (rec.a, rec.b);
exception
when dup_val_on_index then
null;
end;
end loop;
end;
Whenever you get an Oracle error message you don't understand, the first thing to do is look up the meaning. One way is simply to Google it. In this case the full description found in
Oracle9i Database Error Messages is:
ORA-01791 not a SELECTed expression
Cause: There is an incorrect ORDER
BY item. The query is a SELECT DISTINCT query with an ORDER BY clause.
In this context, all ORDER BY items must be constants, SELECT list
expressions, or expressions whose operands are constants or SELECT
list expressions.
Action: Remove the inappropriate ORDER BY item from the SELECT list
and retry the statement.
(Oddly this error message isn't documented in the 10G or 11G manuals, despite still being raised!)
This matches the statement you have written, which is a SELECT DISTINCT query where you are trying to order the results by a column that you did not select.
If you think about it, what you are asking for doesn't make sense: by selecting DISTINCT values that do not include sam.stoptime (for example) you may be consolidating many rows with different values for sam.stoptime, so which one would govern the ordering?
Also, as Noel's answer points out, there is no reason to have an ORDER BY clause in this code anyway, so the solution is simply to remove it.
If you are using DISTINCT in your SELECT query, then your ORDER BY clause should contain only those columns that your selecting. In this case sam.stoptime, sam.uidsamtbpdr are not there in SELECT statement. You can remove the ORDER BY clause, as it is not doing anything useful in your example.

Resources