Oracle SQL - Case statement with iteration - sql

The ASCII table values should be compared to the s.manure_type. For each record in the following table below the QuantityText case statement should do a comparison. The value it needs to select is e.g. oats,velvet beans, other none.
select
c.id customer_num,
c.type type,
s.id_text sample_num,
c.sasa_grower_code s_grower,
c.address s_address1,
c.postalcode s_post_code,
c.email q1_email,
nvl(c.client_name, c.farm_name )s_company,
c.farm_name s_estate,
c.contact_name s_contact,
s.id_numeric id_numeric,
s.id_text fas_lab_id,
s.date_received received_date,
s.date_printed printed_date,
s.sampled_date sampled_date,
e.name S_AREA_DESCRIP,
a.name s_advisor_name,
a.email s_advisor_email,
s.order_no s_order_num,
s.field_name s_field,
p.phrase_text || ' cm' sample_depth,
cr.crop_name s_crop,
s.attyield s_yield,
s.variety s_varty,
case when s.flg_trashed is null then
'None'
else (case when s.flg_trashed = constant_pkg.get_true then
'Yes'
else (case when s.flg_trashed = constant_pkg.get_false then
'No'
else ' '
end)
end) end trashed,
case when s.flg_irrigated is null then
'None'
else (case when s.flg_irrigated = constant_pkg.get_true then
'Yes'
else (case when s.flg_irrigated = constant_pkg.get_false then
'No'
else ' '
end)
end) end s_irrig,
CASE
WHEN trim(s.manure_type) in (select p.phrase_id from phrase p where p.phrase_type = 'AL_G_MANUR') then (select p.phrase_text from phrase p)
END AS QuantityText,
'' S_GM_YIELD,
s.project_code project_code,
s.trial_ref trial_ref,
s.cost_centre cost_centre
from client c
left outer join sample s on (s.client_id = c.id)
left outer join extension e on (e.id = c.extension_id)
left outer join advisor a on (a.id = c.advisor_id)
left outer join phrase p on (p.phrase_id = s.depth)
left outer join crop cr on (cr.id = s.crop_id)
where p.phrase_type = phrase_pkg.get_soil_depth
and c.id = '211493A'
and s.fas_sample_type = sample_pkg.get_soil_sample
and s.flg_recommendation = sample_pkg.get_flg_recommendation
and s.id_numeric between 14932 and 14933
+----------------------------+
| Phrase |
+----------------------------+
|AL_G_MANUR OA Oats |
|AL_G_MANUR V Velvet Beans
|AL_G_MANUR O Other
|AL_G_MANUR N None |
+----------------------------+
But I get the error ORA-00900: Single row query returns more than one row

Missing where clause in one of the case statements is most likely the cause.
CASE
WHEN trim(s.manure_type) in
(select p.phrase_id from phrase p where p.phrase_type = 'AL_G_MANUR')
then (select p.phrase_text from phrase p) <<< NO WHERE CLAUSE ?
END AS QuantityText,
This is relatively easy to debug yourself.
Remove a single selected column
Check if error still occurs
If it does, go back to 1.
If it does not then verify why last added column errors

Problem is in the following statement
then (select p.phrase_text from phrase p)
I guess, It should be replaced with this
(select p.phrase_text from phrase p where p.phrase_type = 'AL_G_MANUR')

Related

Convert multiple rows to columns but as one rows

How do i achieve achieve all this records under one row since every employee has one of each NHIF, NSSF and KRA number?
Below is the query i used but the all appear separate rows.
SELECT DISTINCT
hrmemployeehdr.employeeslno,
hrmemployeehdr.employeecode,
hrmemployeehdr.employeefirstname,
hrmemployeehdr.employeemiddlename,
hrmemployeehdr.employeelastname,
hrmDesignationHdr.DesignationName,
hrmemployeehdr.DateOfBirth,
hrmemployeehdr.DateOfJoin,
hlocationhdr.locationname,
hrmEmployeeIdentityDtl.IDProofReferenceNo AS [National ID],
(CASE
WHEN hrmEmployeeDeductionSettingsDtl.DeductionCode = 1 THEN hrmEmployeeDeductionSettingsDtl.EmployeeRegID
ELSE ''
END) AS NHIF,
(CASE
WHEN hrmEmployeeDeductionSettingsDtl.DeductionCode = 2 THEN hrmEmployeeDeductionSettingsDtl.EmployeeRegID
ELSE ''
END) AS NSSF,
(CASE
WHEN hrmEmployeeDeductionSettingsDtl.DeductionCode = 3 THEN hrmEmployeeDeductionSettingsDtl.EmployeeRegID
ELSE ''
END) AS KRA,
hrmemployeestatusdtl.Email AS [Employee Email],
huser.email AS [User Account Email],
hrmEmployeeGradeHdr.GradeName,
hDepartment.DepartmentName
FROM hrmemployeehdr
JOIN hrmemployeestatusdtl ON hrmemployeestatusdtl.employeeslno = hrmemployeehdr.employeeslno
JOIN hdivision ON hdivision.divisioncode = hrmemployeestatusdtl.divisioncode
JOIN hlocationhdr ON hlocationhdr.locationcode = hrmemployeestatusdtl.workinglocationcode
JOIN hDepartment ON hDepartment.DepartmentCode = hrmemployeestatusdtl.DepartmentCode
JOIN hrmDesignationHdr ON hrmDesignationHdr.DesignationCode = hrmemployeestatusdtl.DesignationCode
JOIN hrmEmployeeCategoryHdr ON hrmEmployeeCategoryHdr.CategoryCode = hrmemployeestatusdtl.CategoryCode
JOIN hrmEmployeeGradeHdr ON hrmEmployeeGradeHdr.GradeCode = hrmemployeestatusdtl.GradeCode
LEFT JOIN huser ON huser.employeeslno = hrmemployeehdr.employeeslno
JOIN hMasterValue ON hMasterValue.MasterValueID = hrmemployeestatusdtl.MasterValue_EmploymentStatusID
JOIN hrmEmployeeIdentityDtl ON hrmEmployeeIdentityDtl.EmployeeSlno = hrmemployeehdr.EmployeeSlno
INNER JOIN hMasterValue a ON a.MasterValueID = hrmEmployeeIdentityDtl.MasterValue_IDProofTypeID
INNER JOIN hrmEmployeeDeductionSettingsDtl ON hrmEmployeeDeductionSettingsDtl.EmployeeSlno = hrmemployeehdr.EmployeeSlno
LEFT JOIN hrmDeductionHdr ON hrmDeductionHdr.DeductionCode = hrmEmployeeDeductionSettingsDtl.DeductionCode
WHERE hrmemployeestatusdtl.employeeslno NOT IN (SELECT hrmemploymentstoppageandtermination.employeeslno
FROM hrmemploymentstoppageandtermination)
AND hrmEmployeeIdentityDtl.MasterValue_IDProofTypeID = 2741005
--and hrmemployeestatusdtl.email = huser.email
--and huser.isemployee = 1
-- select * from huser
ORDER BY employeefirstname ASC;
Use conditional aggregation on the detail table to condense all those rows into one for each employee. Something like:
with edet as (select employeeslno,
max(CASE DeductionCode when 1 THEN EmployeeRegID ELSE '' END) AS NHIF,
max(CASE DeductionCode when 2 THEN EmployeeRegID ELSE '' END) AS NSSF,
max(CASE DeductionCode when 3 THEN EmployeeRegID ELSE '' END) AS KRA
from dbo.hrmEmployeeDeductionSettingsDtl
group by employeeslno)
select emp.employeeslno, ...,
edet.NHIF, edet.NSSF, edet.KRA, ...
from dbo.hrmemployeehdr as emp
inner join edet on emp.employeeslno = edet.employeeslno
...
order by ...
;
Notice the formatting changes that HELP everyone read and understand the code as well as the good habits of using aliases, schema-qualified table names, statement terminator, etc. As already mentioned, the other joins might be contributing to the problem - but this addresses the 1:3 relationship between the header and detail table.

How to use a non-existing column in sql query

I am working in SQL server 2012. I have to write a sql statement where I first assign a value to [Pay_Type], which is a non-existing column (not sure whether it can be called as variable or not) and based upon its value I want to use it in another case statement as shown below
SELECT sp.First_Name, [Pay_Type] = CASE WHEN NOT EXISTS(SELECT '1' FROM
PERSON_SALARY ps WHERE ps.PARTY_ID = sp.PARTY_ID and ps.END_DATE IS NULL)
THEN 'Hourly' ELSE 'Salary' END,
HOURLY_RATE = CASE WHEN [Pay_Type] = 'Hourly' THEN pj.HOURLY_RATE ELSE
'0.00' END
FROM SEC_PERSON sp
LEFT OUTER JOIN PERSON_JOB pj ON sp.PERSON_ID = pj.PERSON_ID
WHERE sp.END_DATE IS NOT NULL
But I am getting "Invalid column name 'Pay_Type' " error.
Column aliases cannot be re-used in the same SELECT where they are define. The typical answer is to use a subquery or CTE. I also like using a lateral join:
SELECT sp.First_Name, s.Pay_Type,
HOURLY_RATE = (CASE WHEN s.Pay_Type = 'Hourly' THEN pj.HOURLY_RATE ELSE
'0.00' END)
FROM SEC_PERSON sp LEFT OUTER JOIN
PERSON_JOB pj
ON sp.PERSON_ID = pj.PERSON_ID OUTER APPLY
(SELECT (CASE WHEN NOT EXISTS (SELECT 1
FROM PERSON_SALARY ps
WHERE ps.PARTY_ID = sp.PARTY_ID and ps.END_DATE IS NULL
)
THEN 'Hourly' ELSE 'Salary'
END) as PayType
) s
WHERE sp.END_DATE IS NOT NULL

Column 'sip.sip.Application.Id' is invalid in the select list

i have an query that is returning "Column 'sip.sip.Application.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause" error. But i have already included that column in the group by. So i'm not sure why it's still returning this error.
SQL Query
SELECT DISTINCT
a.[ApplicationId]
,a.[Id]
,a.[CompanyId]
,c.name AS CompanyName
,a.[CourseSIPRunId]
,ss.[AdminNo]
,count(CASE ss.StudentStatusCode WHEN 'ASG' THEN 1 ELSE 0 END) NoOfStudentsAllocated
,project.NoOfStudents
,project.[CourseCode]
,a.[AppStatusCode]
,appstat.AppStatusDescription
,project.[ProjectId]
,project.ProjectDescription
,a.CourseSIPRunId
,siprun.[AcadYear] + '-' + siprun.[Batch] As SIPBatch
,c.CompanyUEN
,c.PostalCode AS CompanyPostalCode
,course.CourseName
,project.[ResearchFlag] AS ResearchFlagString
,project.MPFlag AS MPFlagString
,project.[SIPType]
,project.ProjectDescription
,case when project.[SIPType]='OSIP' then 1 else 0 END IsOSIP
,case when project.[ResearchFlag] ='Y' then 1 else 0 END IsResearch
,case when project.[MPFlag] ='Y' then 1 else 0 END IsResearch
,project.MentorProjectLeader
,a.[SpecialRequirement]
,a.[MthlyAllowance]
,a.[OtherAllowance]
,a.[DaysPerWeek]
,a.[WeekdayHoursFrom]
,a.[WeekdayHoursTo]
,a.[SaturdayHoursFrom]
,a.[SaturdayHoursTo]
,a.[SundayHoursFrom]
,a.[SundayHoursTo]
,a.[ShiftWorkRequirement]
,a.[TPContactStaffEmailId]
,a.[SIPConfirmationDate]
,a.[SIPConfirmationBy]
,a.[Remarks]
,a.[SelfSource]
,a.[CreateSource]
,a.[CreatedDate]
,a.[SIPAllocationDate]
,a.[SIPAllocationBy]
,a.[SIPClosureDate]
,a.[SIPClosedBy]
,a.[LastUpdatedBy]
,a.[LastUpdatedDate]
,a.[AppStatusCode]
,a.[StatusReason]
,a.[OSIPCountryCode]
,a.[OSIPState]
,a.[OSIPCity]
,a.[OSIPDetails]
,a.[OverseasAssignment]
,a.[OverseasFrequency]
,a.[OverseasOtherCountry]
,a.[OverseasCountryCode]
,a.[OSIPOtherCountry]
,a.[OthersDetails]
,a.[OthersTPContactName]
,a.[OthersTPDiploma]
,a.[OthersEngagement]
,siprun.[StartDate]
,siprun.[EndDate]
,case when appotherinfo.AppOptionCode is null then 0 else 1 END IsInterviewRequired
,appotherinfo.AppOptionCode
FROM [sip].[sip].[Application] a
LEFT join [sip].[ApplicationStatus] appstat on a.AppStatusCode = appstat.AppStatusCode
LEFT join [sip].[ApplicationProject] project on a.ApplicationId = project.ApplicationId
LEFT JOIN [sip].[ApplicationProjectLO] lo on project.ProjectId = lo.ProjectId
LEFT JOIN [sip].[StudentSIP] ss on ss.ProjectId = lo.ProjectId
LEFT JOIN [sip].[ApplicationProjectSupervisor] s on s.ProjectId = project.ProjectId
LEFT JOIN [sip].[Company] c on c.CompanyId = a.CompanyId
LEFT JOIN [sip].[CourseSIPRun] siprun on a.CourseSIPRunId = siprun.CourseSIPRunId
LEFT JOIN [sip].[V_SIP_COURSE] course on project.CourseCode = course.COURSECODE
LEFT JOIN [sip].[ApplicationOtherInfo] appotherinfo on appotherinfo.ApplicationId = a.ApplicationId
group by a.[ApplicationId]
You include a.[ApplicationId] you don't include a.[Id] The error message is about the 2nd one.

SQL joins returning multiple results

select
tmp.templatedesc Template
,sec.name Section
,q.questiontext Questions,
--,sum(case when q.responserequired = '0' then 1 else null end) as 'N/A'
--,sum(case when q.responserequired = '1' then 1 else null end) as Scored
--,count (case when (qr.weightedscore is not null and tmp.templatedesc = 'QA 30 Day Call Form' and
--sec.name = 'opening' and
--rv.reviewstatusid = 1 )then 1 else null end) as scored
----,(case when qr.weightedscore <> q.weight then rv.reviewid else null end) as fail
--count (case when qr.weightedscore is null then 1 else null end) NA,
--count (case when qr.weightedscore is not null then 1 else null end) scored,
sec.sequencenumber, q.questionnumber, qr.*
from
aqm.dbo.reviewtemplate tmp (nolock)
inner join aqm.dbo.section sec on sec.templateid =tmp.templateid
inner join aqm.dbo.sectionresult scr on scr.sectionid = sec.sectionid
inner join aqm.dbo.questionresult qr on qr.sectionresultid = scr.sectionresultid
inner join aqm.dbo.question q on q.questionid = qr.questionid
--inner join aqm.dbo.questiontype qt on qt.questiontypeid = q.questiontypeid
--left outer join aqm.dbo.questionoption qo on qo.questionid = q.questionid
inner join aqm.dbo.review rv on tmp.templateid = rv.templateid
inner join aqm.dbo.media md on md.mediaid = rv.mediaid
inner join aqm.dbo.iqmuser ut on md.userid = ut.userid
where
rv.reviewstatusid = 1 and
tmp.templatedesc = 'QA 30 Day Call Form'
and sec.name = 'opening' and
convert(varchar,dateadd(hh,-7,rv.reviewdate), 101) = '07/07/2014'
and ut.windowslogonaccount = 'name.name'
and q.questionnumber = 4
--group by
--tmp.templatedesc , sec.name, q.questiontext, sec.sequencenumber, q.questionnumber
order by
sec.sequencenumber, q.questionnumber
the questionresultid and sectionresultid are returning multiple values
how can i fix the joins so that it doesnt return multiple values?
i have it drilled down to a date and a person so that it should only return one row of results( but that obviously didnt work)
not sure what other data i can provide
update
i think it has to do with joins
inner join aqm.dbo.sectionresult scr on scr.sectionid = sec.sectionid
inner join aqm.dbo.questionresult qr on qr.sectionresultid = scr.sectionresultid
as those are the ones returning multiple results.
just dont know how to fix it
First, neither aqm.dbo.questiontype nor aqm.dbo.questionoption are used in your return fields or your where clause so get rid of them if they aren't required.
Second, you are OUTER JOINing on the aqm.dbo.review, but the reviewstatusid and reviewdate are required in the WHERE clause - so this should probably be an INNER JOIN.
Last, best way to debug issues like this is to comment out the COUNT statements and the GROUP BY clause - and see what raw data is being returned.

TOP Returning null

I have the following view below. The second nested select is always returning null when I use the TOP(1) clause, but when I remove this clause it returns the data as expected, just more rows than is needed. Does anyone see anything that would explain this?
SELECT TOP (100) PERCENT
a.ITEMID AS Model
,id.CONFIGID
,id.INVENTSITEID AS SiteId
,id.INVENTSERIALID AS Serial
,it.ITEMNAME AS Description
,CASE WHEN it.DIMGROUPID LIKE '%LR-Y' THEN 'Y'
ELSE 'N'
END AS SerialNumberReqd
,ISNULL(it.PRIMARYVENDORID, N'') AS Vendor
,ISNULL(vt.NAME, N'') AS VendorName
,id.INVENTLOCATIONID AS Warehouse
,id.WMSLOCATIONID AS Bin
,ISNULL(CONVERT(varchar(12), CASE WHEN C.DatePhysical < '1901-01-01'
THEN NULL
ELSE C.DatePhysical
END, 101), N' ') AS DeliveryDate
,CASE WHEN (a.RESERVPHYSICAL > 0
OR C.StatusIssue = 1)
AND c.TransType = 0 THEN C.PONumber
ELSE ''
END AS SoNumber
,'' AS SoDetail
,ISNULL(C.PONumber, N'') AS RefNumber
,ISNULL(CONVERT(varchar(12), CASE WHEN ins.ProdDate < '1901-01-01'
THEN NULL
ELSE ins.PRODDATE
END, 101), N' ') AS DateReceived
,it.STKSTORISGROUPID AS ProdGroup
,ISNULL(CONVERT(varchar(12), CASE WHEN ins.ProdDate < '1901-01-01'
THEN NULL
ELSE ins.PRODDATE
END, 101), N' ') AS ProductionDate
,it.ITEMGROUPID
,it.STKSTORISGROUPID AS MerchandisingGroup
,CASE WHEN a.postedValue = 0
THEN (CASE WHEN D.CostAmtPosted = 0 THEN D.CostAmtPhysical
ELSE D.CostAmtPosted
END)
ELSE a.POSTEDVALUE
END AS Cost
,CASE WHEN a.PHYSICALINVENT = 0 THEN a.Picked
ELSE a.PhysicalInvent
END AS PhysicalOnHand
,ins.STKRUGSQFT AS RugSqFt
,ins.STKRUGVENDSERIAL AS RugVendSerial
,ins.STKRUGVENDDESIGN AS RugVendDesign
,ins.STKRUGEXACTSIZE AS RugExactSize
,ins.STKRUGCOUNTRYOFORIGIN AS RugCountryOfOrigin
,ins.STKRUGQUALITYID AS RugQualityId
,ins.STKRUGCOLORID AS RugColorId
,ins.STKRUGDESIGNID AS RugDesignId
,ins.STKRUGSHAPEID AS RugShapeId
,CASE WHEN (a.AVAILPHYSICAL > 0) THEN 'Available'
WHEN (id.WMSLOCATIONID = 'NIL') THEN 'Nil'
WHEN (a.RESERVPHYSICAL > 0)
AND (c.TransType = 0) THEN 'Committed'
WHEN (a.RESERVPHYSICAL > 0) THEN 'Reserved'
WHEN (id.WMSLOCATIONID LIKE '%-Q') THEN 'Damaged'
WHEN (a.Picked > 0) THEN 'Picked'
ELSE 'UNKNOWN'
END AS Status
,'' AS ReasonCode
,'' AS BaseModel
,ISNULL(CAST(ins.STKSTORISCONFIGINFO AS nvarchar(1000)), N'') AS StorisConfigInfo
,ISNULL(C.ConfigSummary, N'') AS ConfigSummary
FROM
dbo.INVENTSUM AS a WITH (NOLOCK)
INNER JOIN dbo.INVENTDIM AS id WITH (NOLOCK)
ON id.DATAAREAID = a.DATAAREAID
AND id.INVENTDIMID = a.INVENTDIMID
LEFT OUTER JOIN dbo.INVENTTABLE AS it WITH (NOLOCK)
ON it.DATAAREAID = a.DATAAREAID
AND it.ITEMID = a.ITEMID
LEFT OUTER JOIN dbo.VENDTABLE AS vt WITH (NOLOCK)
ON vt.DATAAREAID = it.DATAAREAID
AND vt.ACCOUNTNUM = it.PRIMARYVENDORID
LEFT OUTER JOIN dbo.INVENTSERIAL AS ins WITH (NOLOCK)
ON ins.DATAAREAID = id.DATAAREAID
AND ins.INVENTSERIALID = id.INVENTSERIALID
LEFT OUTER JOIN (SELECT TOP (1)
itt.ITEMID
,invt.INVENTSERIALID
,itt.DATEPHYSICAL AS DatePhysical
,itt.TRANSREFID AS PONumber
,itt.TRANSTYPE AS TransType
,itt.STATUSISSUE AS StatusIssue
,dbo.stkRowsToColumn(itt.INVENTTRANSID, 'STI') AS ConfigSummary
,itt.RECID
FROM
dbo.INVENTTRANS AS itt WITH (NOLOCK)
INNER JOIN dbo.INVENTDIM AS invt WITH (NOLOCK)
ON invt.DATAAREAID = itt.DATAAREAID
AND invt.INVENTDIMID = itt.INVENTDIMID
WHERE
(itt.DATAAREAID = 'STI')
AND (itt.TRANSTYPE IN (0, 2, 3, 8))
AND (invt.INVENTSERIALID <> '')
ORDER BY
itt.RECID DESC) AS C
ON C.ITEMID = a.ITEMID
AND C.INVENTSERIALID = id.INVENTSERIALID
LEFT OUTER JOIN (SELECT TOP (1)
itt2.ITEMID
,invt2.INVENTSERIALID
,itt2.COSTAMOUNTPOSTED AS CostAmtPosted
,itt2.COSTAMOUNTPHYSICAL + itt2.COSTAMOUNTADJUSTMENT AS CostAmtPhysical
,itt2.RECID
FROM
dbo.INVENTTRANS AS itt2 WITH (NOLOCK)
INNER JOIN dbo.INVENTDIM AS invt2 WITH (NOLOCK)
ON invt2.DATAAREAID = itt2.DATAAREAID
AND invt2.INVENTDIMID = itt2.INVENTDIMID
WHERE
(itt2.DATAAREAID = 'STI')
AND (itt2.TRANSTYPE IN (0, 2, 3, 4, 6, 8))
AND (invt2.INVENTSERIALID <> '')
ORDER BY
itt2.RECID DESC) AS D
ON D.ITEMID = a.ITEMID
AND D.INVENTSERIALID = id.INVENTSERIALID
WHERE
(a.DATAAREAID = 'STI')
AND (a.CLOSED = 0)
AND (a.PHYSICALINVENT > 0)
AND (it.ITEMGROUPID LIKE 'FG-%'
OR it.ITEMGROUPID = 'MULTISHIP')
ORDER BY
SiteId
,Warehouse
Presumably, the top value in the subquery doesn't meet the subsequent join conditions. That is, this condition is not met:
D.ITEMID = a.ITEMID AND D.INVENTSERIALID = id.INVENTSERIALID
You are using a left outer join, so NULL values are filled in.
EDIT:
To re-iterate. When you run it with top 1, there are no values (for at least some combinations of the two variables). So, NULL will be filled in for these values. After all, top 1 (with or without the parentheses) returns only one row.
When you run it returning multiple rows, presumably there are matches. For the rows that match, the corresponding values are put it. This is the way that left outer join works.
Gordon's answer is correct as to why I was getting a few rows when removing top and none when I had it. The subquery in question was returning all the rows in the InventTrans table (5 million+) so when I used top, it was just getting the first row which didn't have anything. I realized this was the case when I was trying random high values (e.g 50000) in the TOP clause.
The ultimate fix was to change the left outer joins on the C and D subqueries to Cross Apply, and then change the where clauses to better filter the table (e.g itt.itemid = a.itemid and invt1.inventserialid = id.inventserialid). Using that, I was able to use TOP 1 as expected.