ORA-00905: missing keyword due to multiple CASE Conditions - oracle

I m gettingmissing keyword error due to multiple CASE WHEN logic. Below is my code
select inv.ROUTE_APPROVED_BY_CMM as CMM_APPROVED_LENGTH, inv.SPAN_TYPE, ROUND(SUM(NVL(CALCULATED_LENGTH,0)/1000),4) AS NE_LENGTH,
ROUND(SUM(CASE WHEN RJ_CONSTRUCTION_METHODOLOGY NOT LIKE '%AERIAL%' OR RJ_CONSTRUCTION_METHODOLOGY IS NULL THEN NVL(CALCULATED_LENGTH,0) ELSE 0 END)/1000,4) AS UG_LENGTH
,ROUND(SUM(CASE WHEN RJ_CONSTRUCTION_METHODOLOGY LIKE '%AERIAL%' THEN NVL(CALCULATED_LENGTH,0) ELSE 0 END)/1000,4) AS AR_LENGTH,
ROUND(SUM(CASE WHEN RJ_CONSTRUCTION_METHODOLOGY NOT LIKE '%AERIAL%' OR RJ_CONSTRUCTION_METHODOLOGY IS NULL THEN NVL(CALCULATED_LENGTH,0) ELSE 0 END)/1000,4)/ ROUND(SUM(NVL(CALCULATED_LENGTH,0)/1000),4)*100 as ug_percentage
,mv.rj_intracity_link_id FROM NE.MV_SPAN#DB_LINK_NE_VIEWER mv
join TBL_FIBER_INV_CMP_REPORT_MV inv
on (CASE WHEN inv.SPAN_TYPE = 'INTERCITY' THEN inv.SPAN_LINK_ID = mv.rj_span_id ELSE END)
CASE WHEN inv.SPAN_TYPE = 'INTRACITY' THEN inv.SPAN_LINK_ID = mv.rj_intracity_link_id ELSE END)
CASE WHEN inv.SPAN_TYPE = 'ENTERPRISE' THEN inv.SPAN_LINK_ID = mv.rj_intracity_link_id ELSE END)
GROUP BY mv.rj_intracity_link_id, inv.ROUTE_APPROVED_BY_CMM, inv.SPAN_TYPE;

You can't have ELSE END without anything in between, but you also can't have a condition to evaluate as the WHEN or ELSE clause.
You can use Boolean logic rather than case expressions:
join TBL_FIBER_INV_CMP_REPORT_MV inv
on ((inv.SPAN_TYPE = 'INTERCITY' AND inv.SPAN_LINK_ID = mv.rj_span_id)
or (inv.SPAN_TYPE = 'INTRACITY' AND inv.SPAN_LINK_ID = mv.rj_intracity_link_id)
or (inv.SPAN_TYPE = 'ENTERPRISE' AND inv.SPAN_LINK_ID = mv.rj_intracity_link_id))

You cannot return a condition (Boolean) from a CASE like this:
CASE WHEN inv.SPAN_TYPE = 'INTRACITY' THEN inv.SPAN_LINK_ID = mv.rj_intracity_link_id ELSE END
Instead you can use a CASE expression like this:
ON inv.SPAN_LINK_ID = CASE inv.SPAN_TYPE
WHEN 'INTERCITY' THEN mv.rj_span_id
WHEN 'INTRACITY' THEN mv.rj_intracity_link_id
WHEN 'ENTERPRISE' THEN mv.rj_intracity_link_id
END

Related

SQLAlchemy custom boolean

I have an Oracle database with boolean logic implemented this way:
MYCOL NUMBER(1,0)
0 = False
-1 or 1 = True
NULL = None
With a default SQLAlchemy boolean column, -1 table value doesn't match False or True.
Is it possible to create an SQLAlchemy custom type that maps such a column to a bool python attribute?
The difficulty relies in having multiple values associated with true.
Ex:
session.query(User).filter_by(active=True)
Should generate one of these queries:
select * from user where active != 0;
select * from user where active in (-1, 1);
select * from user where 1 = (CASE WHEN active != 0 THEN 1 ELSE active end);
This implementation seems to work for basic queries.
Case when expression seems to be the easiest solution because operator logic isn't altered.
class CustomBoolean(sqlalchemy.types.TypeDecorator):
"""0 = False
-1 or 1 = True
NULL = None
By default, SQLAlchemy only supports 0 and 1"""
impl = Boolean
cache_ok = True
# In select or group by clause, replace col with expression: (CASE WHEN col != 0 THEN 1 ELSE col end)
def column_expression(self, col):
expr = col.expr
if isinstance(expr.type, CustomBoolean):
res = sqlalchemy.case(
(type_coerce(expr, Integer()) != sqlalchemy.literal_column("0", type_=Integer), sqlalchemy.literal_column("1", type_=Integer)),
else_=type_coerce(expr, Integer())
)
return type_coerce(res, Boolean())
expr.type = Boolean()
return expr
# In where clause, replace col with expression: (CASE WHEN col != 0 THEN 1 ELSE col end)
class comparator_factory(Boolean.Comparator):
def operate(self, op, other, **kwargs):
op1 = self
if hasattr(op1, "__clause_element__"):
clause = op1.__clause_element__()
if isinstance(clause.type, CustomBoolean):
op1 = self.normalise(clause)
op2 = other
if hasattr(op2, "__clause_element__"):
clause = op2.__clause_element__()
if isinstance(clause.type, CustomBoolean):
op2 = self.normalise(clause)
return op(
op1, op2, **kwargs
)
#staticmethod
def normalise(expr):
res = sqlalchemy.case(
(type_coerce(expr, Integer()) != sqlalchemy.literal_column("0", type_=Integer), sqlalchemy.literal_column("1", type_=Integer)),
else_=type_coerce(expr, Integer())
)
return type_coerce(res, Boolean())

How to convert sql sum with case to linq

SUM(CASE WHEN [dbo].[tblHits].IsLike = 1 THEN 1 ELSE 0 END) as Likes
i want some thing like this ,below code is giving me error
cannot implicitly convert type bool? to decimal?
TotalLikes = grouped.Sum(d => d.IsLike == true ? d.IsLike = true : d.IsLike = false )
The most direct translation would be:
TotalLikes = grouped.Sum(d => d.IsLike == true ? 1 : 0)
which can be shortened to:
TotalLikes = grouped.Sum(d => d.IsLike ? 1 : 0)
but I would use:
TotalLikes = grouped.Count(d=>d.IsLike);

Multiple Case Statements with Aliases - FROM keyword not found where expected

Here's my code below. When I remove the aliases from the case statements the code runs just fine, and if I leave the alias on the case statement right before the FROM it still works as well. The error I'm getting is FROM keyword not found where expected.
SELECT
HST."HST_DBT_NO",
HST."HST_FLDB",
HST."HST_DATE",
OLI."OLI_FRST_SCHED_DATE",
A."REFERRAL_AMOUNT",
DBT."DBT_FLD_06",
(DBT."DBT_REFERRAL_DATE" - D."DEM_DOB")/365,
(CASE
WHEN A."CLIENT_REF_NUM_1" IS NULL THEN 'NC'
WHEN A."CLIENT_REF_NUM_1" IS NOT NULL THEN 'C'
ELSE NULL
END) AS Check,
(CASE
WHEN A."CLIENT_REF_NUM_2" = 'Checkless Installment Loan' THEN 0
WHEN A."CLIENT_REF_NUM_2" = 'Smart Installment Loan' THEN 0
WHEN A."CLIENT_REF_NUM_2" = 'California Payday Loan' THEN 0
WHEN A."CLIENT_REF_NUM_2" = 'California Checkless Loan' THEN 0
WHEN A."CLIENT_REF_NUM_2" = 'DSI Loan' THEN 0
WHEN A."CLIENT_REF_NUM_2" = 'Mississippi Checkless Loan' THEN 0
WHEN A."CLIENT_REF_NUM_2" = 'Mississippi Payday Loan' THEN 0
WHEN A."CLIENT_REF_NUM_2" = 'PLS Choice Loan' THEN 1
WHEN A."CLIENT_REF_NUM_2" = 'PLS Checkless Choice Loan' THEN 1
WHEN A."CLIENT_REF_NUM_2" = 'Wisconsin Checkless Loan' THEN 1
WHEN A."CLIENT_REF_NUM_2" = 'Wisconsin Installment Loan' THEN 1
WHEN A."CLIENT_REF_NUM_2" = 'Indiana Payday Loan' THEN 1
WHEN A."CLIENT_REF_NUM_2" = 'PLRA Loan' THEN 1
WHEN A."CLIENT_REF_NUM_2" = 'Indiana Checkless Loan' THEN 1
ELSE NULL
END) AS Veritec,
(CASE
WHEN SUBSTR(DBT."DBT_FLD_06",LENGTH(DBT."DBT_FLD_06")-1,2) = 'CI' THEN (SUBSTR(DBT."DBT_FLD_06",LENGTH(DBT."DBT_FLD_06")-5,4)*1)-1
WHEN SUBSTR(DBT."DBT_FLD_06",LENGTH(DBT."DBT_FLD_06")-1,2) = 'SI' THEN (SUBSTR(DBT."DBT_FLD_06",LENGTH(DBT."DBT_FLD_06")-5,4)*1)-1
WHEN SUBSTR(DBT."DBT_FLD_06",LENGTH(DBT."DBT_FLD_06")-1,2) = 'CD' THEN (SUBSTR(DBT."DBT_FLD_06",LENGTH(DBT."DBT_FLD_06")-5,4)*1)-1
WHEN SUBSTR(DBT."DBT_FLD_06",LENGTH(DBT."DBT_FLD_06")-1,2) = 'SD' THEN (SUBSTR(DBT."DBT_FLD_06",LENGTH(DBT."DBT_FLD_06")-5,4)*1)-1
ELSE (SUBSTR(DBT."DBT_FLD_06",LENGTH(DBT."DBT_FLD_06")-3,4)*1)-1
END) AS PriorLoans,
(CASE
WHEN OLI."OLI_FREQUENCY" = 'W' THEN 'WEEKLY'
WHEN OLI."OLI_FREQUENCY" = 'B' THEN 'BI-WEEKLY'
WHEN OLI."OLI_FREQUENCY" = 'V' THEN 'TWICE PER MONTH'
WHEN OLI."OLI_FREQUENCY" = 'M' THEN 'MONTHLY'
ELSE NULL
END) AS PayFrequency,
(CASE
WHEN OLI."OLI_PAYMENT_AMOUNT" > A."REFERRAL_AMOUNT" THEN 'Single Payment'
WHEN OLI."OLI_PAYMENT_AMOUNT" <= A."REFERRAL_AMOUNT" THEN 'Installment'
ELSE NULL
END) AS Type,
(CASE
WHEN HST."HST_DATE" - OLI."OLI_FRST_SCHED_DATE" < 5 THEN 1
WHEN HST."HST_DATE" - OLI."OLI_FRST_SCHED_DATE" >= 5 THEN 0
ELSE NULL
END) AS FirstPayment
FROM "CSS"."HST" HST
LEFT OUTER JOIN "CSS"."ACTUARY_NUMBERS" A
ON HST."HST_DBT_NO" = A."DEBTOR_NO"
LEFT OUTER JOIN "CSS"."DEM" D
ON HST."HST_DBT_NO" = D."DEM_DBT_NO"
LEFT OUTER JOIN "CSS"."DBT" DBT
ON HST."HST_DBT_NO" = DBT."DBT_NO"
LEFT OUTER JOIN "CSS"."OLI" OLI
ON HST."HST_DBT_NO" = OLI."OLI_DBT_NO"
WHERE (HST."HST_TYPE" = 'SC')
AND (HST."HST_DATE" = {ts '2015-04-22 00:00:00'})
AND (HST."HST_FLDB" = 'PSD')
AND (D."DEM_DOB" IS NOT NULL)

Having trouble trying to order using linq

I am trying to order by start date(s.StartDate). Below is my code so far, my understanding is that I should be adding .orderby(s.StartDate) somewhere but I don't think I'm even taking the correct route now as I have tried many ways.
var query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
select s;
var query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
if (startDate != null)
{
query = query.Where(s => s.StartDate >= startDate && s.StartDate <= endDate);
}
You should be able to start with the "without startdate" option - you have a couple of options here - either declare the type of the query specifically:
IQueryable<SessionSearch> query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
order by s.StartDate
select s;
And then as you've tried, add the additional where clause to the query if there's a start date passed in:
query = query.Where(s => s.StartDate >= startDate && s.StartDate <= endDate);
This means that you would not be able to add further ordering via the ThenBy methods.
Alternatively, you can add the order by clause after you've finished adding the where clauses:
var query = from s in context.SessionSearch
where s.Children == 0 && s.IsPublic == isPublic
select s;
if (startDate != null) {
query = query.Where(s => s.StartDate >= startDate && s.StartDate <= endDate);
}
query = query.OrderBy(s => s.StartDate);
Props to JonSkeet for pointing these out.

Help needed on SQL query to Linq Conversion

Please help me write LINQ for this SQL
select svc.SvcName, svcOptions.SvcOptionName, svcMap.Price from svcMap
inner join
svc
on svcMap.SvcId = svc.SvcId
inner join
svcOptions
on svcOptions.SvcOptionId = CASE WHEN (svcMap.DesiredSvcOptionId <> 0 AND svcMap.DesiredSvcOptionId <> svc.DisabledSvcOptionId) THEN
svcMap.DesiredSvcOptionId
WHEN (svcMap.PresentSvcOptionId <> svc.DisabledSvcOptionId) THEN
svcMap.PresentSvcOptionId
ELSE
0
END
where svcMap.ToBill = 1
and
(
(svcMap.DesiredSvcOptionId = 0 AND svcMap.PresentSvcOptionId <> svc.DisabledSvcOptionId)
OR
(svcMap.DesiredSvcOptionId <> 0 AND svcMap.DesiredSvcOptionId <> svc.DisabledSvcOptionId)
)
SOLUTION
This is the solution that I implemented and it gave me exactly what I needed when I cross checked it with LinqPad
from svcMap in db.ServicesMap
join svc in db.Services on svcMap.SvcId equals svc.SvcId
join option in db.Options on
((svcMap.DesiredSvcOptionId != 0 && svcMap.DesiredSvcOptionId != svc.DisabledSvcOptionId)
? svcMap.DesiredSvcOptionId
: (svcMap.PresentSvcOptionId != svc.DisabledSvcOptionId)
? svcMap.PresentSvcOptionId
: 0)
equals option.SvcOptionId
where svcMap.ToBill == 1
&& (
(svcMap.DesiredSvcOptionId == 0 &&
svcMap.PresentSvcOptionId != svc.DisabledSvcOptionId)
||
(svcMap.DesiredSvcOptionId != 0 &&
svcMap.DesiredSvcOptionId != svc.DisabledSvcOptionId)
)
select
new
{
svc.SvcName,
option.SvcOptionName,
svcMap.Price.GetValueOrDefault()
}
Why have a CASE in your joining criteria? What do you expect the optimizer to do with that exactly?
Here's a literal translation.
from svcMap in db.svcMaps
where svcMap.ToBill == 1
let svc = svcMap.Svc
where (svcMap.Desired == 0 && svcMap.Present <> svc.Disabled)
|| (svcMap.Desired <> 0 && svcMap.Desired <> svc.Disabled)
let optionId =
svcMap.Desired <> 0 && svcMap.Desired <> svc.Disabled ? svcMap.Desired :
svcMap.Present <> svc.Disabled ? svc.Present :
0
from option in db.Options
where option.SvcOptionId == optionId
select new {svc.SvcName, option.SvcOptionName, svcMap.Price }

Resources