How to loop cy.task according to the result - random

I'm testing the CRUDs for a page in my application, where a registry requires an unique ID as a 5 digit number to be successfully created.
I would like to get a random available ID of that table to use in the tests, that can be achieved with the following sql query:
cy.task(
'sqlQuery',
`select count(*) as "count" from clients where client_id = '${
Math.floor(Math.random() * 90000) + 10000
}'`
)
The point is that the random number perhaps is not available to be used as the ID, so i would need to loop this same task until the generated number is available:
cy.task(
'sqlQuery',
`select count(*) as "count" from clients where client_id = '${
Math.floor(Math.random() * 90000) + 10000
}'`
).then((result: any) => {
if (result.rows[0].count === 0) {
// My code to submit the form with the generated number
// break the loop
} else {
// Repeat all of this (where i'm asking for help)
}
})
If count returns 0 it means it's there's no registry using it, otherwise it's not available.
I guess the final solution could be using some while loop, but I found this way would be more clear to you all know what i'm needing.
I tried some approachs like this, but just discovery that its impossible to assign a new value to a variable inside the .then block, so it seems like i did an endless loop.
let available = false
do {
cy.task(
'sqlQuery',
`select count(*) as "count" from clients client_id = '${
Math.floor(Math.random() * 90000) + 10000
}'`
).then((result: any) => {
if (result.rows[0].count === 0) {
// Code to submit the form with the generated number
available = true
}
})
} while (available === false)

Ask SQL what ids are present and check the random one against those?
Something like this:
cy.task('sqlQuery', 'select client_id from clients')
.then((result: any) => {
const ids: string[] = result.rows;
function getNewId(trys = 0) {
if (trys > 1000) throw new Error('failed')
const newId = Math.floor(Math.random() * 90000) + 10000
if (ids.includes(newId)) {
return getNewId(++trys)
}
return newId
}
const newId = getNewId()
cy.wrap(newId).as('newId')
})
Update
Changed to a recursive javascript function, as I found when testing .should() it does not re-evaluate Math.floor(Math.random() * 90000) + 10000
It's been a while since I did some SQL, but maybe this correlated subquery is more efficient
SELECT last + 1 as newId FROM (
SELECT MAX(id) as last FROM clients
)

You can use a query like this to get 3 unused IDs for your tests
MySQL:
SELECT a.id+1 as 'ids'
FROM clients a
WHERE
NOT EXISTS (SELECT * FROM clients b WHERE a.id+1 = b.id) AND
a.id+1 < 100000
ORDER BY a.id
LIMIT 3
Oracle 11:
SELECT a.id+1 as ids
FROM clients a
WHERE
NOT EXISTS (SELECT * FROM clients b WHERE a.id+1 = b.id) AND
a.id+1 < 10000 AND
rownum <= 3
ORDER BY a.id;
Oracle 12:
SELECT a.id+1 as ids
FROM clients a
WHERE
NOT EXISTS (SELECT * FROM clients b WHERE a.id+1 = b.id) AND
a.id+1 < 10000
ORDER BY a.id
FETCH FIRST 3 ROWS ONLY;
This will search for unused IDs checking always the next ID, limiting it to 3 rows (you can limit the amount you need) to improve performance. And only available IDs, under 100000 (has only 5 digits)
For example:
Your table has de IDs (1, 3, 5, 6, 7, 9, 10)
This query will check if the IDs (2, 4, 6, 8, 10, 11) exist in the table. If it doesnt exists, it will return. So this example will return (2, 4, 8)

Related

Return duplicate min values

See the table below for reference. I need to return duplicate rows containing the min value.
In this example I want to show only the 2 rows that have SLAT_LEN = 30 or rather the min SLAT_LEN. I tried rank but when I do it does a consecutive rank. I want the duplicate sizes to have the same rank and to rank consecutively by size.
The sizes change so I can't just use a condition like SLAT_LEN = 30.
Or is there a different approach that I should take?
select *
from(
select lg.wd_demand_id,wm.slat_len, wm.prof_size, wm.wd_material_id, wm.color, rank() over ( partition by wm.slat_len order by lg.wd_demand_id) as rank
from wd_demand_log lg, wd_bins wb, wd_material wm, wd_bins_material wbm
where lg.wd_bins_id = wb.wd_bins_id
and lg.wd_material_id = wm.wd_material_id
and lg.wd_bins_id = wbm.wd_bins_id
and lg.wd_material_id = wbm.wd_material_id
AND lg.plant_id = 44 AND lg.dept_id = 220 AND wb.plant_id = 44 AND wb.dept_id = 220
AND NOT EXISTS(SELECT dmpln.wd_demand_id FROM wd_demnd_pln_inv dmpln WHERE dmpln.wd_demand_id = lg.wd_demand_id)
AND wm.prof_size = '2' AND wm.color = 450
AND lg.wd_po_error is null)
You'd use PARTITION BY to give the range in which to rank. The ORDER BY specifies the ranking. So in your case you'll need something like
rank() over (order by wm.slat_len)
In case you have Oracle 12c you can limit your results with FETCH FIRST:
ORDER BY wm.slat_len
FETCH FIRST 1 ROW WITH TIES;
Perhaps I am not understanding the problem correctly, but here is my potential solution:
WITH aset
AS (SELECT lg.wd_demand_id
, wm.slat_len
, wm.prof_size
, wm.wd_material_id
, wm.color
FROM wd_demand_log lg, wd_bins wb, wd_material wm
, wd_bins_material wbm
WHERE lg.wd_bins_id = wb.wd_bins_id
AND lg.wd_material_id = wm.wd_material_id
AND lg.wd_bins_id = wbm.wd_bins_id
AND lg.wd_material_id = wbm.wd_material_id
AND lg.plant_id = 44
AND lg.dept_id = 220
AND wb.plant_id = 44
AND wb.dept_id = 220
AND NOT EXISTS
(SELECT dmpln.wd_demand_id
FROM wd_demnd_pln_inv dmpln
WHERE dmpln.wd_demand_id = lg.wd_demand_id)
AND wm.prof_size = '2'
AND wm.color = 450
AND lg.wd_po_error IS NULL)
SELECT *
FROM aset
WHERE slat_len = (SELECT MIN (slat_len)
FROM aset)

Calculation in query based on the condition

I have a package in oracle contains several procedures, in one of those procedures I need to calculate some fee based on specific condition like this:
if X_flag = 1
then
fee = (.5 * orders.total_count) + (.3 * orders.total_amount)
else
fee = (.7 * orders.total_count) + (.4 * orders.total_amount)
so, what is the better way to do that?
The procedure that I need to add this calculation on it :
procedure informatonRPT (
p_customerID in number,
p_orderID in number)
as
begin
select
cusromers.costomerId,
cusromers.costomerName,
cusromers.coustomerPhone,
orders.price
from cusromers
inner join orders
on cusromers.orderId = orders.orderID
when
p_customerID is null or p_customerID = cusromers.costomerId
and p_orderID is null or p_orderID = orders.orderID ;
end informatonRPT;
customers table columns:
customerID
custumerName
customerPhone
ordedID
order table columns:
orderID
price
total_Amount
total_count
Note that:
Fee column doesn't exist in the data base, I have to calculate it in query
Again Im not sure because you didnt provide enought information, but you need use a CASE expresion
SELECT C.costomerId,
C.costomerName,
C.coustomerPhone,
O.price,
CASE X_flag
WHEN 1 THEN (.5 * O.total_count) + (.3 * O.total_amount)
ELSE 7 * O.total_count) + (.4 * O.total_amount)
END as fee
FROM cusromers C
join orders O
on C.orderId = O.orderID
oracle CASE documentation

Single-row subquery returns more than one row- update with nested selects and substr

I'm trying to write a query for a table that needs to update certain records based on certain perameters. I have several nested selects and a couple of nested substrings which I imagine are what is making it difficult for me to troubleshoot. I solved a couple of these ORA-01427: single row sub-query returns more than one row problems already, but I can't seem to find this one. Essentially what the script is doing is taking two columns from a record and updating them based another record contained within a different table based on a number of different criteria. Below is the current code I am using:
UPDATE CMC_SBEL_ELIG_ENT p
SET (p.CSPI_ID, p.SBEL_EFF_DT) =
(SELECT co.new_plan, co.ch_dt
FROM sbsb_plan_conv co, cmc_sbel_elig_ent p
WHERE co.ch_dt > p.sbel_eff_dt
and co.ch_dt < current_date
AND co.new_plan <> p.CSPI_ID
AND co.sbsb_ck = p.sbsb_ck
AND p.cspi_id IN co.OLD_PLAN
and p.SBEL_ELIG_TYPE IN ('tm','ce','TM','CE')
)
WHERE (p.cspd_cat IN (
select unique substr(o.old_plan, 1, 1)
from facets_ws.sbsb_plan_conv o
where
substr(o.old_plan, 1, 1) IN (
select substr(y.new_plan, 1, 1)
from sbsb_plan_conv y, cmc_sbel_elig_ent u
where y.sbsb_ck = u.sbsb_ck
AND (p.SBEL_ELIG_TYPE IN ('tm','ce','TM','CE'))
and ((substr(y.new_plan, 1, 1) = 'M'
and substr(y.new_plan, 1, 1) != 'R'
and substr(y.new_plan, 1, 1) != 'D')
or (substr(y.new_plan, 1, 1) = 'R'
and substr(y.new_plan, 1, 1) != 'M'
and substr(y.new_plan, 1, 1) != 'D')
or (substr(y.new_plan, 1, 1) = 'D'
and substr(y.new_plan, 1, 1) != 'R'
and substr(y.new_plan, 1, 1) != 'M'))
and o.sbsb_ck = p.sbsb_ck)
)
);
Now when I run the individual queries on the two select statements, they all return definite unique values. So I'm fairly certain they are not the issue.
try executing the following query :-
SELECT count(co.new_plan)
FROM sbsb_plan_conv co, cmc_sbel_elig_ent p
WHERE co.ch_dt > p.sbel_eff_dt
and co.ch_dt < current_date
AND co.new_plan <> p.CSPI_ID
AND co.sbsb_ck = p.sbsb_ck
AND p.cspi_id IN co.OLD_PLAN
and p.SBEL_ELIG_TYPE IN ('tm','ce','TM','CE')
group by co.new_plan;
If the above returns more than one row or if it returns a count more than one, then you might need to change the query to either do a DISTINCT / MIN / use ROWNUM or some other technique.

having difficulty writing this in LINQ

The application is a basic stock-analysis app.
The data-set looks like this:
`ABC, True, 21/09/2012, 101.34
ABC, False, 21/09/2012, 202.45
CDE, True, 21/09/2012, 345.67
ABC, True, 22/09/2012. 456.78
`
The SQL is here:
SELECT TickerCode, Australian from Stk_ClosingPrices group by TickerCode,
Australian having count(*) >= #daysToAverageOver order by TickerCode
What I would like as a result would be grouping by the first two fields,and a count of how many in each group. For the above that would be:
ABC, True, 2
ABC, False, 1
CDE, True, 1
And then I would like to return only those with Count > parameter passed in.
The algorithm is going to calculate a 20-day moving average, so in English the query is 'Give me the keys of stocks with more than 20 data records'
This is how far I have got, but I can't get the Count right, it is always the same for every group.
var query = (from cp in this.ObjectContext.stk_ClosingPrices group cp by new {
cp.TickerCode, cp.Australian
}
into grp
select new {
grp.Key.TickerCode, grp.Key.Australian,
Count = grp.Distinct()
}).ToList();
I have seen an example similar with a grp.Sum(Quantity) but could not seem to be able to re-cast that to .Count() predicate.
Many thanks,
Try
var query1 = (from cp in this.ObjectContext.stk_ClosingPrices group cp by new {
cp.TickerCode, cp.Australian
}
into grp
select new {
grp.Key.TickerCode, grp.Key.Australian,
Count = grp.Count()
});
var results = (from r in query where r.Count > 20 orderby r.TickerCode select r).ToList();
Will actually produce SQL like
SELECT TickerCode, Australian, Count
FROM (
SELECT COUNT(*) AS Count, TickerCode, Australian
FROM Stk_ClosingPrices
GROUP BY TickerCode, Australian
) AS t1
WHERE t1.Count > 20
Order By t1.TickerCode

Translate SQL query without FROM clause to LINQ

How to translate query like "select 1, 2" (i.e. without FROM clause) to LINQ statement?
Thanks!
I need to get permissions for a set of user groups. In SQL it looks like
SELECT *
FROM Permission p
INNER JOIN (SELECT GroupID
FROM [Group]
UNION ALL
SELECT 555) AS g
ON (g.GroupID = p.GroupID)
In my case I need to programmatically add a certain code instead "555". I wouldn't like to write special SQL function for that.
I guess you just want to create an anonymous type
var anonymous = new { Column1 = 1, Column2 = 2 };
Edit - Based on Comments
Depending on what your Select projection is you could do something simple like this:
If it is a Int:
var query = (from per in context.permissions
select per).AsEnumerable()
.Concat( new int[] { 1, 2 });
If it is a 'Class'
var query = (from per in context.permissions
select per).AsEnumerable()
.Concat(new CustomClass[]
{
new CustomClass()
{
Prop1= 1
},
}
);
You could also change .Concat to .Union
Why do you need this to be linq?
var numbers = new int[] { 1, 2 };
I suppose
var numbers = Enumerable.Range(1,2);

Resources