Matching criteria for the below scenario - sql

Refer to above image. I had tables Diagnoses,Services and PreventativeServices in which i have a common field named DxCode in diagnosis and PreventativeServices. DxCode in PreventativeServices table is an optional field as it acts as a configuration table for us. Suppose DxCode = DiagnosisCode, I have following scenarios, based on image:
If we have DxCode in both services and diagnosis table then compare it on DxCode and resultant row should be output of the comparison. If found output will be 10060 else no row.
If we have DxCode = null or blank in PreventativeServices then again output will be 10060.
If we dont have rows in our Diagnosis table against RegistrationId = 247237 but we have a row in PreventativeServices with along with diagnosis code then again resultant will be no row, else
out put will be 10060
I had following query for the same:
SELECT [ServiceID] AS PreventativeServiceId,
[CPTCode]
FROM PreventativeService ps
INNER JOIN [Services] s(NOLOCK)
ON ps.CPTCode = s.ServiceCode
LEFT JOIN Diagnoses dx(NOLOCK)
ON dx.RegistrationID = s.RegistrationID
WHERE s.RegistrationId = #RegistrationId
AND ps.IsActive = 1
AND #AdmitDate BETWEEN ps.StartDate AND Isnull(PS.EndDate, #AdmitDate)
AND #Gender = Isnull(ps.Gender, #Gender)
AND #Age BETWEEN Isnull(ps.AgeFrom, #Age) AND Isnull(ps.AgeTo, #Age)
AND dx.DiagnosisCode = ( CASE
WHEN Rtrim(Ltrim(ps.DiagnosisCode)) = '' THEN dx.DiagnosisCode
ELSE ps.DiagnosisCode
END )
NOTE
DiagnosisCode in PreventativeServices will contain null and blank as well.
Requirement
dx.DiagnosisCode = ( CASE
WHEN Rtrim(Ltrim(ps.DiagnosisCode)) = '' THEN dx.DiagnosisCode
ELSE ps.DiagnosisCode
END )
is failing for scenario , when I have blank('') diagnosis in PreventativeServices and no row in Diagnosis table

ok, This is because null=null always returns false. You can try using isnull function.
isnull(dx.DiagnosisCode,' ') = (
CASE
WHEN rtrim(ltrim(ps.DiagnosisCode)) = ''
THEN isnull(dx.DiagnosisCode,' ')
ELSE ps.DiagnosisCode
END
)

Related

How to Update to SET Table1.ColumnX = Table2.ColumnX with a where clause

Let's say I have one table called InsuranceMember which contains all members of insurance plans and their spouses. But oh no! for spouses that have a CountryCD of 'Canada' and have a PlanCD of '99999', the MemberNum's (primary key) are all incorrect in this table!
But thankfully, there is a table called InsurancePlan, that contains spouses, and where these Spouses's MemberNum's (also primary key) are all correct!
So in this hypothetical I need a conditional update statement that sets InsuranceMember.MemberNum = InsurancePlan.MemberNum where CountryCD = 'Canada' and PlanCD = '99999'
How can I write a query to make this work and update each row.
When I've tried writing this query I always get back this error:
-811
THE RESULT OF AN EMBEDDED SELECT STATEMENT OR A SUBSELECT IN THE SET CLAUSE OF AN UPDATE STATEMENT IS A TABLE OF MORE THAN ONE ROW, OR THE RESULT OF A SUBQUERY OF A BASIC PREDICATE IS MORE THAN ONE VALUE
This is very confusing for me as a beginner in SQL, but I'm sure the situation I'm describing is something many have dealt with.
Edit: Here is an example of code I use that produces that update:
UPDATE PRD.InsuranceMember mem
set mem.MemberNum = ( Select pln.MemberNum
from PRD.InsurancePlan pln
where mem.MemberNum <> pln.MemberNum
and mem.MoneySource = pln.MoneySource
)
WHERE mem.MemberNum = (SELECT pln2.MemberNum FROM PRD.InsurancePlan pln2
WHERE mem.ClientCd = pln2.ClientCd
AND mem.PLanCd = pln2.PlanCd)
AND Mem.MoneySource='3'
AND Mem.CountryCd = 'Canada'
AND Mem.PlanCd = '99999'
;
Try adding a FETCH FIRST ROW ONLY to the end of each of your subqueries, which will inform the database that those expressions will not return multiple values.
UPDATE PRD.InsuranceMember mem
SET mem.MemberNum = ( SELECT pln.MemberNum
FROM PRD.InsurancePlan pln
WHERE mem.MemberNum <> pln.MemberNum
AND mem.MoneySource = pln.MoneySource
FETCH FIRST ROW ONLY
)
WHERE mem.MemberNum = (SELECT pln2.MemberNum
FROM PRD.InsurancePlan pln2
WHERE mem.ClientCd = pln2.ClientCd
AND mem.PLanCd = pln2.PlanCd
FETCH FIRST ROW ONLY
)
AND mem.MoneySource='3'
AND mem.CountryCd = 'Canada'
AND mem.PlanCd = '99999'
;
Using an UPDATE of a SELECT can help in this situation as you can run just the SELECT part and ensure that the newMemberNum sub-select only returns one row
UPDATE (
SELECT
MemberNum
, MoneySource
, CountryCd
, PlanCd
, ( Select pln.MemberNum
from PRD.InsurancePlan pln
where mem.MemberNum <> pln.MemberNum
and mem.MoneySource = pln.MoneySource
) AS NewMemberNum
FROM
PRD.InsuranceMember mem
)
SET MemberNum = NewMemberNum
WHERE
MoneySource='3'
AND CountryCd = 'Canada'
AND PlanCd = '99999'
AND MemberNum IS DISTINCT FROM NewMemberNum
So you might need a MAX(pln.MemberNum) or DISTINCT some such in the sub-select to ensure that at most one row is found for each selected row in PRD.InsuranceMember

Condition if sql

I have this query
SELECT
SI_Num_Inventario = COALESCE (t.SI_Num_Inventario, c.SI_Num_Inventario),
SI_Ubicacion = COALESCE(t.SI_Ubicacion, c.SI_Ubicacion),
SI_Ubicacion_Fisica = COALESCE(t.SI_Ubicacion_Fisica, c.SI_Ubicacion_Fisica),
SI_Num_Articulo = COALESCE(t.SI_Articulo, c.SI_Num_Articulo),
NULL,
SI_Num_Conteo = COALESCE(cs.SI_Num_Conteo,2),
GETDATE(),
'Admin',
c.SI_OV
FROM
SI_Inventario_Teorico_QAD t
FULL JOIN
SI_Conteo c ON t.SI_Articulo = c.SI_Num_Articulo
AND t.SI_Ubicacion = c.SI_Ubicacion
INNER JOIN
SI_Maestro_Ref_QAD m ON t.SI_Articulo = m.SI_Num_Articulo
OR c.SI_Num_Articulo = m.SI_Num_Articulo
FULL JOIN
SI_Consecutivo cs ON c.SI_Num_Inventario = cs.SI_Num_Inventario
AND cs.SI_Estado = 0
WHERE
c.SI_Num_Articulo = 201423 OR t.SI_Articulo = 201423
And I'm trying to tell you that if c.SI_OV IS NULL INSERT THIS `INSERT INTO``
IF c.SI_OV IS NULL
INSERT INTO SI_Conteo(SI_Num_Inventario, SI_Ubicacion,SI_Num_Articulo, SI_Cantidad,SI_Num_Conteo,SI_Fecha_Conteo, SI_Usuario,SI_OV)
And if it is not NULL insert me this other
ELSE
INSERT INTO SI_Conteo(SI_Num_Inventario, SI_Ubicacion_Fisica, SI_Num_Articulo, SI_Cantidad,SI_Num_Conteo,SI_Fecha_Conteo, SI_Usuario,SI_OV)
END IF;
In short: the CASE construct needs to "live" in your SELECT clause of you SQL statement. The receiving INSERT clause should always mention both column names like this
INSERT INTO SI_CONTEO (SI_Num_Inventario,
SI_Ubicacion, SI_Ubicacion_fisico,
SI_Num_Articulo, SI_Cantidad,SI_Num_Conteo,
SI_Fecha_Conteo, SI_Usuario,SI_OV)
SELECT SI_Num_Inventario = COALESCE (t.SI_Num_Inventario,c.SI_Num_Inventario),
SI_Ubicacion = CASE WHEN SI_OV IS NULL THEN COALESCE(t.SI_Ubicacion, c.SI_Ubicacion) END,
SI_Ubicacion_Fisica = CASE WHEN NOT SU_OV IS NULL THEN COALESCE(t.SI_Ubicacion_Fisica, c.SI_Ubicacion_Fisica) END,
SI_Num_Articulo = COALESCE(t.SI_Articulo, c.SI_Num_Articulo),
NULL, ...
if else in non query language ~= CASE WHEN cond1 ELSE cond2 END in SQL
Use the below query:
INSERT INTO SI_Conteo(SI_Num_Inventario,SI_Ubicacion,SI_Ubicacion_Fisica,SI_Num_Articulo, SI_Cantidad,SI_Num_Conteo,SI_Fecha_Conteo,
SI_Usuario,SI_OV)
SELECT
SI_Num_Inventario = COALESCE (t.SI_Num_Inventario,c.SI_Num_Inventario),
(CASE WHEN c.SI_OV IS NULL THEN COALESCE(t.SI_Ubicacion, c.SI_Ubicacion) ELSE NULL END)AS SI_Ubicacion,
(CASE WHEN c.SI_OV IS NOT NULL THEN COALESCE(t.SI_Ubicacion_Fisica, c.SI_Ubicacion_Fisica) ELSE NULL END)AS SI_Ubicacion_Fisica,
SI_Num_Articulo = COALESCE(t.SI_Articulo, c.SI_Num_Articulo),
NULL,
SI_Num_Conteo = COALESCE(cs.SI_Num_Conteo,2),
GETDATE(),
'Admin',
c.SI_OV
FROM SI_Inventario_Teorico_QAD t
full JOIN SI_Conteo c
ON t.SI_Articulo = c.SI_Num_Articulo
AND t.SI_Ubicacion = c.SI_Ubicacion
INNER JOIN SI_Maestro_Ref_QAD m
ON t.SI_Articulo = m.SI_Num_Articulo
OR c.SI_Num_Articulo = m.SI_Num_Articulo
FULL JOIN SI_Consecutivo cs
ON c.SI_Num_Inventario = cs.SI_Num_Inventario
AND cs.SI_Estado = 0
WHERE c.SI_Num_Articulo = 201423 OR t.SI_Articulo = 201423
Basicallly I have combined both inserts into one Insert, which includes both of the columns , where you want a switch based on Case. Only one column out of SI_Ubicacion and SI_Ubicacion_Fisica will be set based on s.SI_OV value. Hope you got what I am saying,.
Note: I Could not execute this as I don't have any table structure/data with me. I have modified your query manually and posted it here.
Clarify your question. You have a select statement that returns a resultset of some number of rows. You propose to insert them into a table. You claim to need to use if/else (or similar) but it is not clear why. Your proposed insert statements differ by a single column - is that correct? If so, then you probably need to use 2 different insert statements - one to handle the non-null situation and one to handle the null situation. You cannot dynamically change the column list of the inserted table.
OTOH, perhaps you just want to swap the value inserted into the SI_Ubicacion column of the SI_Conteo table? If so, you can probably use isnull or coalesce in the select statement (much like you do now - just differently).

Case Statement with IS NULL not acting as required

Good Evening,
I have the following sql code and need to replace the NULL values within a sub query. As you can tell from the code I have tried using the ISNULL function and case where = NULL.
Could someone please help?
Select Student_Details.STU_ID ,
( Select case ISNULL( s1stu_disability_type.DISABILITY_TYPE_CD , '' )
when '' then 'NO'
else 'YES'
end
from s1stu_disability_type
Where Student_Details.STU_ID = s1stu_disability_type.STU_ID
and DISABILITY_TYPE_CD = '$HEAR'
) as 'Hearing Disability'
from S1STU_DET as Student_Details
Your where clause in your subquery rejects all rows but those where the column DISABILITY_TYPE_CD is '$HEAR'. Consequently, the case statement will always take the else route, as that column will never, ever be null or empty ('').
What exactly are you trying to do?
You query can better be written as
select sd.STU_ID ,
dt.DISABILITY_TYPE_CD
from S1STU_DET sd
join s1stu_disability_type dt on dt.STU_ID = sd.STU_D
and dt.DISABILITY_TYPE_CD = '$HEAR'
It's almost certian that relationship between student and student disability has a zero-to-many cardinalilty, which is to say that each student has zero or more disabilities.
As a result, your original query, with its correlated subquery, will return 1 row per student, but per the SQL standard, it's luck of the draw as to which matching disability gets selected by the subquery.
My query above will return one row per student with a matching disability. Students without a matching disability are excluded. To change that to include all students, you want to change the [inner] join to a left [outer] join. Each student will then be represented in the result set at least once. If the student has no matching disabilities, all columns for the student disability table will be 'null'.
If, as I suspect, what you're trying to do is identify students as to whether or not they have a hearing disability (or some particular type of disability), you need to summarize things. A query like this will likely do you:
select sd.STU_ID ,
case sign(coalesce(hd.cnt,0))
when 1 then 'YES'
else 'NO'
end as HAS_HEARING_DISABILITY
from S1STU_DET sd
left join ( select STU_ID ,
count(*) as cnt
from s1stu_disability
where DISABILITY_TYPE_CD = '$HEAR'
group by STU_ID
) hd on hd.STU_ID = sd.STU_ID
Try this:
Select Student_Details.STU_ID ,
IsNull(( Select case ISNULL( s1stu_disability_type.DISABILITY_TYPE_CD , '' )
when '' then 'NO'
else 'YES'
end
from s1stu_disability_type
Where Student_Details.STU_ID = s1stu_disability_type.STU_ID
and DISABILITY_TYPE_CD = '$HEAR'
), 'No') as 'Hearing Disability'
from S1STU_DET as Student_Details
Basically, the ISNULL function has to be outside the subquery for it to work the way you want it to. Think of it this way, if the subquery does not return any rows, the output will be null whether you have an isnull check inside the subquery or not.
You shouldn't need a subquery (assuming your subquery only returns one record):
Select
Student_Details.STU_ID,
case WHEN Student_Disability.DISABILITY_TYPE_CD IS NULL
THEN 'NO'
ELSE 'YES'
END
as 'Hearing Disability'
from S1STU_DET as Student_Details
LEFT JOIN s1stu_disability_type Student_Disability
ON Student_Details.STU_ID = Student_Disability.STU_ID
and Student_Disability.DISABILITY_TYPE_CD = '$HEAR'

Selecting column value based on another table

I have two tables, one of which contains many fields including fldANA and fldPROD and another table which contains the same two fields. Not all fldANA and fldPROD fields have a matching value in table 2 however and so I don't know as if I can really join the fields? The following is what my query currently looks like but it's returning 10's or 1000's more records than it is supposed to.
SELECT Line#, CastID,
(CASE WHEN #sRst1.PROD = FN_qryIDs.fldANA AND #sRst1.PROD =
FN_qryIDs.fldPROD
THEN FN_qryIDs.fldANA ELSE #sRst1.ANA END) AS ANA,
(CASE WHEN #sRst1.PROD = FN_qryIDs.fldANA AND #sRst1.PROD =
FN_qryIDs.fldPROD
THEN FN_qryIDs.fldCONN ELSE #sRst1.CONN END) AS CONN
INTO #sRst2
FROM #sRst1
WHERE CastID <> '' AND PROD <> '' AND ANA <> ''
Ehm, not sure about the source schema but hopefully this should at least get you on the right path.
SELECT R1.[Line#], R1.CastID
,ISNULL(Q.fldANA, R1.ANA) [ANA]
,ISNULL(Q.fldCONN, R1.CONN) [Conn]
FROM #sRst1 R1
LEFT JOIN FN_qryIDs Q ON Q.fldANA = R1.PROD
AND Q.fldPROD = R1.PROD
WHERE R1.CastID <> ''
AND R1.Prod <> ''
AND R1.ANA <> ''

SQL Query unable to return record

The following SQL works as expected if ProjectStatusType.Name is not null. Therefore I put the case statement which replace null value with 'Not specified'. What I am trying to do is to add a where statement to display ProjectStatusType.Name = 'Not Specified', but no data gets returned, although there is a record in database with null projectstatustype.name. Please advise; what is another way, or how can I fix the SQL query?
SELECT PersonResponsible.Name AS TeamLeaderName,
CASE
WHEN ProjectStatusType.Name IS NULL THEN 'Not Specified'
ELSE COALESCE(ProjectStatusType.Name, '')
END AS ProjectStatusName,
Project.ProjectTitle AS Title,
ProjectStatus.DateStatus,
Project.ProjectId,
Project.ContactName,
BusinessDivision.Name AS BusinessUnit,
BusinessUnit.Name AS WorkSection,
ProjectSubGroup.Name AS ProjectSubGroupName,
ProjectGroup.Name AS ProjectGroupName,
Project.DateRequested
FROM BusinessUnit
INNER JOIN BusinessDivision ON BusinessUnit.BusinessDivisionId = BusinessDivision.BusinessDivisionId
INNER JOIN ProjectCode ON BusinessUnit.BusinessUnitId = ProjectCode.BusinessUnitId
RIGHT OUTER JOIN Project
INNER JOIN ProjectSubGroup ON Project.ProjectSubGroupId = ProjectSubGroup.ProjectSubGroupId
INNER JOIN ProjectGroup ON ProjectSubGroup.ProjectGroupId = ProjectGroup.ProjectGroupId ON ProjectCode.ProjectCodeId = Project.ProjectCodeId
LEFT OUTER JOIN PersonResponsible ON Project.PersonResponsibleId = PersonResponsible.PersonResponsibleId FULL
OUTER JOIN ProjectStatusType
INNER JOIN ProjectStatus ON ProjectStatusType.ProjectStatusTypeId = ProjectStatus.ProjectStatusTypeId
AND ProjectStatus.ProjectStatusId IN
(SELECT MAX(ProjectStatusId) AS ProjectStatusId
FROM ProjectStatus
GROUP BY ProjectId) ON Project.ProjectId = ProjectStatus.ProjectId
WHERE ProjectStatus ProjectStatusType.Name ='Not Specified'
Here is a great chart from Itzik Ben-Gan on how SQL server processes a query. The order is different than how we write T-SQL.
Thus the solution by rutter might miss the empty string.
If I was doing this type of business logic alot, I would write a function that would take both the empty string or null value and return a string 'unknown'. Call this function in the query and filter by 'unknown'.
The example below creates a temporary table, loads the table with data, and returns both the empty string and null value converted to the adjust name 'Not Specified'.
I hope this helps.
I always refer to the logical processing chart when queries do not work the way I think they should.
Good luck
John
--
-- Logical query processing
--
-- From, Where, Group By, Having, Select (expression, distince, top), order by
-- sample table
create table #status
( id int identity(1,1),
name varchar(50) null
);
-- Sample data
insert into #status values
(''),
(null),
('www.craftydba.com');
-- Return rows with null or empty string
select
case when ltrim(name) = '' then 'Not Specified'
else coalesce(name, 'Not Specified') end as adjusted_named,
name
from #status
where
ltrim(name) = '' or
coalesce(name, 'Not Specified') = 'Not Specified';
Two points:
First, a CASE checking for null seems redundant to a COALESCE expression.
This should be simpler:
SELECT COALESCE(ProjectStatusType.Name, 'Not Specified') AS ProjectStatusName
Second, comparing to ProjectStatusType.Name (the value in your table) is not the same as comparing to ProjectStatusName (the value you selected).
Try a WHERE clause closer to this:
WHERE ProjectStatusName = 'Not Specified'