How to rewrite an Impromptu case statement in Cognos Framework Manager? - frameworks

I have a case statement in Impropmtu that I need to recreate in Framework Manager. I need help with case statement syntax in Framework manager, and in this special case, there is a nested statement involved that makes it a bit more complicated.
I tried using the predefined components in Framework Manager to create the case statement but it doesn't work. I am thinking maybe it is because of the syntax.
This is the Impromptu expression from *.IQD file:
CASE
WHEN ((CASE
WHEN ((((((((('D12' || "ACCOUNT1") = 'E4GM') or
(('D12' || "ACCOUNT1") = 'E4M')) or
(('D12' || "ACCOUNT1") = 'DAM')) or
(('D12' || "ACCOUNT1") = 'DGM')) or
(('D12' || "ACCOUNT1") = 'DJM')) or
(('D12' || "ACCOUNT1") = 'DNM')) or
(('D12' || "ACCOUNT1") = 'DQM')) or
(('D12' || "ACCOUNT1") = 'DWM'))
THEN ('Units')
ELSE null END) = 'Units')
THEN (CASE
WHEN ("MODEL" BETWEEN '10%' AND '19%') THEN ('Mini Unit')
WHEN ("MODEL" BETWEEN '21%' AND '22%') THEN ('Small Unit')
WHEN ("MODEL" BETWEEN '32%' AND '33%') THEN ('Medium Unit')
WHEN ("MODEL" BETWEEN '38%' AND '39%') THEN ('Large Unit')
WHEN ("MODEL" BETWEEN 'M3%' AND 'M4%') THEN ('WH Unit')
ELSE null END) ELSE null END as c21,

Related

pyspark sql with inline case when join condition

This is the original SQL with inline case when condition:
select *
from table_a
LEFT JOIN table_b
ON case when table_a.key not in ('1','2') then '0' else table_a.key end = table_b.key
What is the equivalent pyspark code?
I was trying when().otherwise() function and if() function but neither worked.
table_a=spark.sql('''select 1 as key union select 2 as key''')
table_a.show()
table_b=spark.sql('''select 3 as key union select 0 as key''')
table_b.show()
val join_condition = when(((table_a.key == '1') | (table_a.key == '2')), table_a.key == table_b.key).otherwise(('0' == table_b.key))
df = table_a.join(table_b, join_condition, 'leftouter').select(table_a['*'], table_b['*'])
df = table_a.join(table_b, ((if(((table_a.key == '1') | (table_a.key == '2')), ('0'), (table_a.key))) == table_b.key), 'leftouter')\
.select(table_a['*'], table_b['*'])
Thank you!
Whenever you have a multi conditions like this (table_a.key == '1' | table_a.key == '2'), you'd have to wrap each of them separately like this ((table_a.key == '1') | (table_a.key == '2'))

converting sql statement back to lambda expression

I have the query below, and its sql code. It's running really slow, so it was re written in sql, now I'm just not sure how to convert the sql back to a lambda expression.
This is the part of the expression giving me the problems, somewhere in
r.RecordProducts.Any()
records = records
.Include(r => r.Employer)
.Include(r => r.Contractor)
.Include(r => r.RecordProducts)
.ThenInclude(rp => rp.ProductDefendant.Defendant)
.Where(r => EF.Functions.Like(r.Employer.DefendantCode, "%" + input.DefendantCode + "%")
|| EF.Functions.Like(r.Contractor.DefendantCode, "%" + input.DefendantCode + "%")
|| r.RecordProducts.Any(rp => EF.Functions.Like(rp.ProductDefendant.Defendant.DefendantCode, "%" + input.DefendantCode + "%") && rp.IsActive == true));
the any clause does an exist and some funky stuff in the sql where clause below
SELECT [t].[Id], [t].[StartDate], [t].[EndDate], [t].[WitnessName], [t].[SourceCode], [t].[JobsiteName], [t].[ShipName], [t].[EmployerCode]
FROM (
SELECT DISTINCT [r].[RecordID] AS [Id], [r].[StartDate], [r].[EndDate], [r.Witness].[FullName] AS [WitnessName], CASE
WHEN [r].[SourceID] IS NOT NULL
THEN [r.Source].[SourceCode] ELSE N'zzzzz'
END AS [SourceCode], CASE
WHEN [r].[JobsiteID] IS NOT NULL
THEN [r.Jobsite].[JobsiteName] ELSE N'zzzzz'
END AS [JobsiteName], CASE
WHEN [r].[ShipID] IS NOT NULL
THEN [r.Ship].[ShipName] ELSE N'zzzzz'
END AS [ShipName], CASE
WHEN [r].[EmployerID] IS NOT NULL
THEN [r.Employer].[DefendantCode] ELSE N'zzzzz'
END AS [EmployerCode]
FROM [Records] AS [r]
LEFT JOIN [Ships] AS [r.Ship] ON [r].[ShipID] = [r.Ship].[ShipID]
LEFT JOIN [Jobsites] AS [r.Jobsite] ON [r].[JobsiteID] = [r.Jobsite].[JobsiteID]
LEFT JOIN [Sources] AS [r.Source] ON [r].[SourceID] = [r.Source].[SourceID]
LEFT JOIN [Witnesses] AS [r.Witness] ON [r].[WitnessID] = [r.Witness].[WitnessID]
LEFT JOIN [Defendants] AS [r.Contractor] ON [r].[ContractorID] = [r.Contractor].[DefendantID]
LEFT JOIN [Defendants] AS [r.Employer] ON [r].[EmployerID] = [r.Employer].[DefendantID]
WHERE ([r].[IsActive] = 1) AND (([r.Employer].[DefendantCode] LIKE (N'%' + 'cert') + N'%' OR [r.Contractor].[DefendantCode] LIKE (N'%' + 'cert') + N'%') OR EXISTS (
SELECT 1
FROM [Records_Products] AS [rp]
INNER JOIN [Product_Defendant] AS [rp.ProductDefendant] ON [rp].[DefendantProductID] = [rp.ProductDefendant].[DefendantProductID]
INNER JOIN [Defendants] AS [rp.ProductDefendant.Defendant] ON [rp.ProductDefendant].[DefendantID] = [rp.ProductDefendant.Defendant].[DefendantID]
WHERE ([rp.ProductDefendant.Defendant].[DefendantCode] LIKE (N'%' + 'cert') + N'%' AND ([rp].[IsActive] = 1)) AND ([r].[RecordID] = [rp].[RecordID])))
) AS [t]
ORDER BY [t].[SourceCode]
OFFSET 0 ROWS FETCH NEXT 500 ROWS ONLY
Here is the new sql that works better, just not sure how to convert it back to a lambda expression
SELECT [t].[Id]
,[t].[StartDate]
,[t].[EndDate]
,[t].[WitnessName]
,[t].[SourceCode]
,[t].[JobsiteName]
,[t].[ShipName]
,[t].[EmployerCode]
FROM (
SELECT DISTINCT [r].[RecordID] AS [Id]
,[r].[StartDate]
,[r].[EndDate]
,[r.Witness].[FullName] AS [WitnessName]
,CASE
WHEN [r].[SourceID] IS NOT NULL
THEN [r.Source].[SourceCode]
ELSE N'zzzzz'
END AS [SourceCode]
,CASE
WHEN [r].[JobsiteID] IS NOT NULL
THEN [r.Jobsite].[JobsiteName]
ELSE N'zzzzz'
END AS [JobsiteName]
,CASE
WHEN [r].[ShipID] IS NOT NULL
THEN [r.Ship].[ShipName]
ELSE N'zzzzz'
END AS [ShipName]
,CASE
WHEN [r].[EmployerID] IS NOT NULL
THEN [r.Employer].[DefendantCode]
ELSE N'zzzzz'
END AS [EmployerCode]
FROM [Records] AS [r]
LEFT JOIN [Ships] AS [r.Ship] ON [r].[ShipID] = [r.Ship].[ShipID]
LEFT JOIN [Jobsites] AS [r.Jobsite] ON [r].[JobsiteID] = [r.Jobsite].[JobsiteID]
LEFT JOIN [Sources] AS [r.Source] ON [r].[SourceID] = [r.Source].[SourceID]
LEFT JOIN [Witnesses] AS [r.Witness] ON [r].[WitnessID] = [r.Witness].[WitnessID]
LEFT JOIN [Defendants] AS [r.Contractor] ON [r].[ContractorID] = [r.Contractor].[DefendantID]
LEFT JOIN [Defendants] AS [r.Employer] ON [r].[EmployerID] = [r.Employer].[DefendantID]
LEFT JOIN (
SELECT [rp].[RecordID]
FROM [Records_Products] AS [rp]
INNER JOIN [Product_Defendant] AS [rp.ProductDefendant] ON [rp].[DefendantProductID] = [rp.ProductDefendant].[DefendantProductID]
INNER JOIN [Defendants] AS [rp.ProductDefendant.Defendant] ON [rp.ProductDefendant].[DefendantID] = [rp.ProductDefendant.Defendant].[DefendantID]
WHERE (
[rp.ProductDefendant.Defendant].[DefendantCode] LIKE (N'%' + 'cert') + N'%'
AND ([rp].[IsActive] = 1)
)
) AS RecordProduct ON [r].[RecordID] = RecordProduct.[RecordID]
WHERE ([r].[IsActive] = 1)
AND (
(
[r.Employer].[DefendantCode] LIKE (N'%' + 'cert') + N'%'
OR [r.Contractor].[DefendantCode] LIKE (N'%' + 'cert') + N'%'
)
OR RecordProduct.RecordID IS NOT NULL --OR EXISTS ( -- SELECT 1 -- FROM [Records_Products] AS [rp] -- INNER JOIN [Product_Defendant] AS [rp.ProductDefendant] ON [rp].[DefendantProductID] = [rp.ProductDefendant].[DefendantProductID] -- INNER JOIN [Defendants] AS [rp.ProductDefendant.Defendant] ON [rp.ProductDefendant].[DefendantID] = [rp.ProductDefendant.Defendant].[DefendantID] -- WHERE ([rp.ProductDefendant.Defendant].[DefendantCode] LIKE (N'%' + 'cert') + N'%' -- AND ([rp].[IsActive] = 1)) AND ([r].[RecordID] = [rp].[RecordID]) -- ) )) AS [t]ORDER BY [t].[SourceCode]OFFSET 0 ROWS FETCH NEXT 500 ROWS ONLY
)
)
The linq expression you supplied and the SQL generated do not match. For one, the linq expression is performing an Include on the various related tables which would have included all of those entity columns in the top-level SELECT which are not present in your example SQL. I also don't see conditions in the Linq expression for the Take 500 & OrderBy, or IsActive assertion on Record.
To be able to help determine the source of any performance concern we need to see the complete Linq expression and the resulting SQL.
Looking at the basis of the Linq expression you provided:
records = records
.Include(r => r.Employer)
.Include(r => r.Contractor)
.Include(r => r.RecordProducts)
.ThenInclude(rp => rp.ProductDefendant.Defendant)
.Where(r => EF.Functions.Like(r.Employer.DefendantCode, "%" + input.DefendantCode + "%")
|| EF.Functions.Like(r.Contractor.DefendantCode, "%" + input.DefendantCode + "%")
|| r.RecordProducts.Any(rp => EF.Functions.Like(rp.ProductDefendant.Defendant.DefendantCode, "%" + input.DefendantCode + "%") && rp.IsActive == true));
There are a few suggestions I can make:
There is no need for the Functions.Like. You should be able to achieve the same with Contains.
Avoid using Include and instead utilize Select to retrieve the columns from the resulting structure that you actually need. Populate these into ViewModels or consume them in the code. The less data you pull back, the better optimized the SQL can be for indexing, and the less data pulled across the wire. Consuming entities also leads to unexpected lazy-load scenarios as systems mature and someone forgets to Include a new relation.
.
records = records
.Where(r => r.IsActive
&& (r.Employer.DefendantCode.Contains(input.DefendantCode)
|| r.Contractor.DefendantCode.Contains(input.DefendantCode)
|| r.RecordProducts.Any(rp => rp.IsActive
&& rp.ProductDefendant.Defendant.DefendantCode.Contains(input.DefendantCode))
.OrderBy(r => r.SourceCode)
.Select(r => new RecordViewModel
{
// Populate the data you want here.
}).Take(500).ToList();
This also adds the IsActive check, OrderBy, and Take(500) based on your sample SQL.

To find what all condition element is true in a rule

In drool we have any option to find what all condition tuples satisfied in a rule, when I execute a stateless session with fact.
ex: if we have rule condition in a rule RUL1,
car.schi == 'A' || car.carKind str[startsWith] 'A'
if RUL1 is satisfied because of car.schi, then do we have any API where I can get this info(car.schi).
The example what I given was simpler but our actual business rule was so complex as shown below,
(car.carKind != \"EZZ\" && car.carKind != \"ENG\" && car.carKind != \"ETD\") && ((car.schi contains \"N1\" || car.schi contains \"N2\") || ((car.schi contains \"IH\" || car.schi contains \"N4\" || car.schi contains \"OM\" || car.schi contains \"DA\" || car.schi contains \"N5\" || car.schi contains \"PA\" || car.schi contains \"FG\" || car.schi contains \"PL\" || car.schi contains \"PC\" || car.schi contains \"PO\" || car.schi contains \"NG\" || car.schi contains \"OX\" || car.schi contains \"OP\" || car.schi contains \"NS\" || car.schi contains \"FS\" || car.schi contains \"FL\" || car.schi contains \"N3\" || car.schi contains \"CM\" || car.schi contains \"DW\" || car.schi contains \"PB\") && (validateElementRule($trainrulesRequestDTO.getElementRuleMap(),\"1_N\",true,$trainrulesRequestDTO.getCar().getCarNumb())))) && (((car.prevSchi not contains \"N2\" && car.prevSchi not contains \"N1\") && (car.prevLoadEmpty == \"L\") && ((car.prevCarKind str[startsWith] \"F\" || car.prevCarKind str[startsWith] \"YF\") && (car.prevCarKind not str[startsWith] \"FI\" && car.prevCarKind not str[startsWith] \"FA\" && car.prevCarKind not str[startsWith] \"FW\" && car.prevCarKind not str[startsWith] \"FB\") && (car.prevCarKind != \"YFB\"))) || ((car.nextSchi not contains \"N2\" && car.nextSchi not contains \"N1\") && (car.nextLoadEmpty == \"L\") && ((car.nextCarKind str[startsWith] \"F\" || car.nextCarKind str[startsWith] \"YF\") && (car.nextCarKind not str[startsWith] \"FA\" && car.nextCarKind not str[startsWith] \"FB\" && car.nextCarKind not str[startsWith] \"FI\" && car.nextCarKind not str[startsWith] \"FW\") && (car.nextCarKind != \"Y\" || car.nextCarKind != \"YFB\"))))
If we are to split it as different rules to find if the rule was satisfied because of( prevCarKind , prevSchi , prevLoadEmpty) or (nextCarKind, nextSchi,nextLoadEmpty) it would be too hard to split the complex rule.
I have also given the rule condition as image took from our UI application.
Pictorial view of above rule condition string
Would be helpful if someone can let us know on how to find if the above is satisfied based on which condition.
Regards,
Madhankumar. B
Thanks,
Madhan
No you can't. But you could split the rule into multiple rules like this:
rule "RUL1A"
when
car.schi == 'A'
then
...
end
rule "RUL1B"
when
car.carKind[0] == 'A'
then
...
end
You could split your condtion into several functions (and define them in drl):
function boolean isKindEzzEngEtd(Car car) {
return car.carKind in ["EZZ", "ENG", "ETD"];
}
function boolean isSchiContainsN1N2(Car car) {
return (car.schi contains "N1" || car.schi contains "N2");
}
...
then use the functions inside your rules (it also improves readablility and re-use):
rule "RUL1"
when
$car: Car()
!isKindEzzEngEtd($car) || isSchiContainsN1N2($car) && ...
then
-- call the functions one by one to find out which one returned true:
System.out.println("NOT isKindEzzEngEtd: " + !isKindEzzEngEtd($car));
System.out.println("isSchiContainsN1N2: " + isSchiContainsN1N2($car));
end

Full-Text Search producing no results

I have the following View:
CREATE VIEW public.profiles_search AS
SELECT
profiles.id,
profiles.bio,
profiles.title,
(
setweight(to_tsvector(profiles.search_language::regconfig, profiles.title::text), 'B'::"char") ||
setweight(to_tsvector(profiles.search_language::regconfig, profiles.bio), 'A'::"char") ||
setweight(to_tsvector(profiles.search_language::regconfig, profiles.category::text), 'B'::"char") ||
setweight(to_tsvector(profiles.search_language::regconfig, array_to_string(profiles.tags, ',', '*')), 'C'::"char")
) AS document
FROM profiles
GROUP BY profiles.id;
However, if profiles.tags is empty then document is empty, even if the rest of the fields (title, bio, and category) contain data.
Is there some way to make the make that field optional such that it having empty data doesn't result in an an empty document?
This seems to be the common string concatenation issue - concatenating a NULL value makes the whole result NULL.
Here it is suggested you should always provide a default value for any input with coalesce():
UPDATE tt SET ti =
setweight(to_tsvector(coalesce(title,'')), 'A') ||
setweight(to_tsvector(coalesce(keyword,'')), 'B') ||
setweight(to_tsvector(coalesce(abstract,'')), 'C') ||
setweight(to_tsvector(coalesce(body,'')), 'D');
If you do not want to provide default values for complex datatypes (like coalesce(profiles.tags, ARRAY[]::text[]) as suggested by #approxiblue), I suspect you could simply do:
CREATE VIEW public.profiles_search AS
SELECT
profiles.id,
profiles.bio,
profiles.title,
(
setweight(to_tsvector(profiles.search_language::regconfig, profiles.title::text), 'B'::"char") ||
setweight(to_tsvector(profiles.search_language::regconfig, profiles.bio), 'A'::"char") ||
setweight(to_tsvector(profiles.search_language::regconfig, profiles.category::text), 'B'::"char") ||
setweight(to_tsvector(profiles.search_language::regconfig, coalesce(array_to_string(profiles.tags, ',', '*'), '')), 'C'::"char")
) AS document
FROM profiles
GROUP BY profiles.id;

How to make a function use CASE and IFNULL in postgreSQL?

can you tell me how to use CASE and IFNULL in postgre? i'm migrating from sql to postgreSQL, and i want to make a function with this syntax :
SELECT a.furniture_id, a.furniture_brand, a.furniture_cost,
CASE
WHEN furniture_id = f_id THEN a.furniture_content
ELSE ''
END CONTENT
FROM tb_furniture a
WHERE
(IFNULL(a.sale_id,0) = IFNULL(f_id,0) OR (a.furniture_id = f_Id AND IFNULL(a.furniture_content,'') > ''))
AND a.published = 1;
thanks before(y)
This seems to be what you are after, but carefully check the WHERE conditions:
SELECT a.furniture_id, a.furniture_brand, a.furniture_cost,
CASE WHEN a.furniture_id = f_id
THEN a.furniture_content
ELSE ''
END AS content
FROM tb_furniture a
WHERE (coalesce(a.sale_id,0) = coalesce(f_id,0) OR length(content) > 0)
AND a.published = 1;