How to find in vector ( parameter)? - gams-math

If I have a set and parameter
Set A/a1,a9/;
Parameter T(A);
*Suppose p is T(A)=121311332
T(A) /1 1,2 2,3 1,4 3,5 1,6 1,7 3,8 3,9 2/;
How to find the third one and changed it to 4?
(E.g. 121311332 changed to 121341332)
Generally How may I get the nth repetitive element (1,2or 3) from set A and change it?Is there anyway to do that?

Edit after clarification in comments:
To change the third occurrence of 1 to 4 you can do this:
Set A /a1*a9/;
Parameter T(A) /a1 1,a2 2,a3 1,a4 3,a5 1,a6 1,a7 3,a8 3,a9 2/;
Scalar oneCnt / 0 /;
Display T;
loop(A,
if(T(A)=1,
oneCnt = oneCnt+1;
if(oneCnt=3,
T(A)=4;
break;
)
);
);
Display T;
Originally, I thought that the third element should be changed. That could be done like this:
You can use the ord operator (https://www.gams.com/latest/docs/UG_OrderedSets.html#UG_OrderedSets_TheOrdOperator) to do that:
Set A/a1*a9/;
Parameter T(A) /a1 1,a2 2,a3 1,a4 3,a5 1,a6 1,a7 3,a8 3,a9 2/;
Display T;
T(A)$(ord(a)=3) = 4;
Display T;

Related

Remove / backslash from query to get valid data in oracle

With my latest query, I get the data as ABDD_1037/. but I don't want the record which has / in it.
I tried with below query but it's not working
SELECT TO_CHAR(RJ_INTRACITY_LINK_ID) AS SPAN_ID,
TO_CHAR(RJ_MAINTENANCE_ZONE_CODE) AS MAINT_ZONE_CODE
FROM NE.MV_SPAN#DB_LINK_NE_VIEWER
-- FROM APP_FTTX.span#SAT
WHERE LENGTH(RJ_INTRACITY_LINK_ID) > 8
AND LENGTH(RJ_INTRACITY_LINK_ID) < 21
AND INVENTORY_STATUS_CODE = 'IPL'
AND RJ_MAINTENANCE_ZONE_CODE = 'INUEABDD01'
AND NOT REGEXP_LIKE (RJ_INTRACITY_LINK_ID,'_(9|31|4|7|_____|U|[\/]$)','i')
MINUS
SELECT TO_CHAR(LINK_ID) AS SPAN_ID,
TO_CHAR(MAINTENANCEZONECODE) AS MAINT_ZONE_CODE
FROM TBL_FIBER_INV_JOBS
WHERE SPAN_TYPE = 'INTRACITY'
AND MAINTENANCEZONECODE = 'INUEABDD01'
ORDER BY 1;
UPDATE
IF I comment the whole regex line, I would get all the unwanted data like below
`ABDD_0102_U`, `ABDD_1037/`,`ABDD_3102`, `ABDD_4003`, `STHU_9032`,
At the moment your pattern:
'_(9|31|4|7|_____|U|[\/]$'
will match any value which contains _9, _31, _4, _7, ______ (six underscores), _U or _u anywhere; or which ends with _/ (or _<backslash>, which I don't think you intended).
If you want it to match values ending with _<someting>/ then you need to allow for the <something> part, e.g.:
'_(9|31|4|7|_____|U|.*/$)'
If you want it to match values with a / in it anywhere, not just at the end and following an underscore, then you need to separate that from the underscore prefix and remove the $ anchor, e.g.:
'(_(9|31|4|7|_____|U)|/)'
db<>fiddle

How Do I Modify First Digit of Attribute in XML with SQL?

This is the section of my xml I am trying to modify:
<ORDER ORDER_NAME="10009999"
ORDER_NAME is an attribute.
This is what I have come up with so far and I think it's close, but slightly off.
update table_name set txn_message.modify('replace value of (/ORDER/#ORDER_NAME)[.=1000][1] with "2000"') , txn_status = 1
I want to replace 10009999 with 20009999 (really just something else to make it different so data can be reused, adding a additional character is also fine).
One way is
update t
set txn_message.modify('replace value of (/ORDER/#ORDER_NAME)[1] with concat("2", sql:column("vr"))')
from table_name t
cross apply (
select left(t.txn_message.value('(/ORDER/#ORDER_NAME)[1]','varchar(20)'), 1) vl
, substring (t.txn_message.value('(/ORDER/#ORDER_NAME)[1]','varchar(20)'), 2, 8000) vr
) v
where vl = '1';

SQL: delete only if subquery (containing 0, 1, or more rows) equals scalar value

Description
I'm trying to do something like:
DELETE FROM ...
-- `<my_id>` is any given long scalar value
WHERE <my_id> = (SELECT id FROM ... WHERE ...);
That syntax is not entirely correct. If the select subquery contains more than one row, then we get an error like:
Scalar subquery contains more than one row
However, my intended purpose is indeed:
if the subquery returns exactly 1 value equal to the scalar value (<my_id>) ==> delete
else (0, or 2 or more values, or 1 non-equal value) ==> do not delete (ignore)
Question
I do not want neither IN nor EXISTS. I need rather something like "equals", which can compare a scalar value against possibly multi-valued rows.
What is the syntax in SQL for that?
Stack
In particular, I'm testing this with H2.
One method is:
DELETE FROM ...
WHERE <my_id> IN (SELECT id FROM ... WHERE ...) AND
(SELECT COUNT(*) FROM . . . WHERE . . .) = 1;
However, this is more simply written as:
DELETE FROM ...
WHERE <my_id> = (SELECT MAX(id)
FROM . . .
WHERE . .
HAVING COUNT(*) = 1
) ;
If the count is not 1, then the subquery returns nothing and there is no match (so nothing is deleted).

Generate 100 data randomly, or select if it is possible

I want to test my model , I need to test it in some data , I want to generate data , in fact I want to have 125 different parameter from 0 to 10000.
For example , in below we have 4 different parameter ,from 1 to 300.
Set I/0*300/;
Parameter MyParameter;
MyParameter /4 1,10 1,42 1,87 1/;
I don't want to do this by hand.
Is there any method that I generate it automaticly.
another way asking:
how can Select 4 random element of a set ' I' , without repetition?
Try this:
Set I /0*300/
picks /p1*p4/;
Scalar pick;
Parameter MyParameter(I);
MyParameter(I) = 0;
loop(picks,
pick = uniformInt(1, card(I));
* Make sure to not pick the same one twice
while(sum(I$(pick=ord(I)),MyParameter(I))=1,
pick = uniformInt(1, card(I))
Display 'here';
);
MyParameter(I)$(pick=ord(I))=1;
);
Display MyParameter;

Reorder nodes in SQL Hierarchy data type

Using Hierarchy data type on SQL 2008. Nodes in my hierarchy go like this:
value node
36 /8/1/
38 /8/2/
34 /8/3/
40 /8/4/
42 /8/5/
44 /8/6/
46 /8/7/
48 /8/8/
I'd like to rearrange nodes so that /8/3/ and /8/1/ switch places. Any idea on how to do this?
Only idea that I have so far is that I load all nodes on a level in Array, order them the way I want them to be, delete them from table and insert in sorted form.
If (like in your example) you know the hierarchyid values you want to manipulate in advance, you can do it directly, e.g.:
-- Place 1st node between 2nd and 3rd
UPDATE yourTable SET node = CAST('/8/2.5/' AS hierarchyid) WHERE value = 36;
-- Move 3rd node to 1st
UPDATE yourTable SET node = CAST('/8/1/' AS hierarchyid) WHERE value = 34;
If you need to get your new hierarchyid values dynamically, take a look into the GetDescendant() and GetAncestor() functions. Using that, the example would look something like this:
DECLARE #Parent hierarchyid, #Child1 hierarchyid, #Child2 hierarchyid
-- Grab hierarchyids from 2nd and 3rd node
SELECT #Child1 = node FROM yourTable WHERE value = 38;
SELECT #Child2 = node FROM yourTable WHERE value = 34;
-- Get the parent hierarchyid
SELECT #Parent = #Child1.GetAncestor(1);
-- Update 1st node to end up between 2nd and 3rd
UPDATE yourTable SET node = #Parent.GetDescendant(#Child1, #Child2) WHERE value = 36;
-- Update 3rd node to end up before 2nd
UPDATE yourTable SET node = #Parent.GetDescendant(NULL, #Child1) WHERE value = 34;
Note that the hierarchyids do not stay the same in this example. At least one will end up using a 'fraction' for its position (e.g. '/8/2.5/' instead of '/8/3/').
Found the solution
http://technet.microsoft.com/en-us/library/bb677256.aspx