Ignore clauses in where based on if you get a result from the select - sql

I want the following sql statement to give me different results based on whether it finds a result within the specific string or it needs to search the whole parent group (so within the table there are for example:
column 1, column 2
a - 1
a - 2
a - 3
b - 5
b - 7
b - 1
so if it can find the result if i put 1 it will display me
a -1
b -1
. the problem is that in the where clause exist both the parent group and the child group
i have tried to use case and also to simulate an if with ands and ors but it didn't work
select 1,
aapv.aapv_keyext1,
aapv.aapv_area,
aapv.aapv_valuecharmax,
aapv.aapv_valuechardefault,
aapv.aapv_valuecharmin, aap.aap_ident
from a_parameter_value aapv,
a_parameter aap
where aap.aap_ident in (string1,string2,string3)
and aap.aap_ref = aapv.aap_ref
and aap.aap_idento = string4
and ((aapv.Aapv_Keyext1 = 'LaD1' --child clause
and aapv.aapv_keyext1 is not null)
or aapv.Aapv_Area = 'LSDe' --parent clause
and aapv.Aapv_Area is null)
I expect the output to be if the aapv_keyext1 value finds any results then the appv_area is not used at all but either only the child clause is used with the above code or both if i remove the is null clause

Okay, you need to provide more information for us to give you a real answer, but I wanted to point out that this section has some logic problems:
and ((aapv.Aapv_Keyext1 = 'LaD1' --child clause
and aapv.aapv_keyext1 is not null)
or aapv.Aapv_Area = 'LSDe' --parent clause
and aapv.Aapv_Area is null)
The first part is saying aapv_keyext1 = 'LaD1' AND aapv_keyext1 is not null; the second half can never be false, so it's redundant. The second part is saying aapv_area = 'LSDe' AND aapv_area is null. This will never be true. So this whole section is equivalent to:
and (aapv.aapv_keyext1 = 'LaD1')
Which probably isn't what you want. You say you want "if the aapv_keyext1 value finds any results then the appv_area is not used at all". I suspect what you mean is that "if any results exist for aapv_keyext1 in any rows then don't use aapv_area" which is more complicated, you need a subquery (or analytic/aggregate functions) to look at what other rows are doing.
select 1,
aapv.aapv_keyext1,
aapv.aapv_area,
aapv.aapv_valuecharmax,
aapv.aapv_valuechardefault,
aapv.aapv_valuecharmin, aap.aap_ident
from a_parameter_value aapv,
a_parameter aap
where aap.aap_ident in (string1,string2,string3)
and aap.aap_ref = aapv.aap_ref
and aap.aap_idento = string4
and (-- prefer keyext1
aapv.Aapv_Keyext1 = 'LaD1'
OR
-- if keyext1 doesn't find results...
(NOT EXISTS (select 1 from a_parameter_value aapv2
where aapv2.aap_ident = aap.aap_ident
and aap2.aap_ref = aap.aap_ref
and aap2.aap_idento = aap.aap_idento
and aapv.Aapv_Keyext1 = 'LaD1')
AND
-- ... use aapv_area
aapv.Aapv_Area = 'LSDe')
);
You can also do this kind of conditional logic with CASE statements, but you're still going to need a subquery or something if you want your logic to depend on the values in rows other than the one currently being looked at.
Let me know if I've misunderstood your question and I'll try to update with a better answer.

Related

using case statement in a where clause

Hello I am missing something because my code errors.
select * from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where (ScheduleDate = testdate)
and
(Case
when HF.IsHoliday = 1 then (overtime = 1 and makeup = 0)
else
(overtime = 0 and Makeup = 0)
end
)
and
DOW = 5
order by ActivityStartTime
I've attempted several combinations and each one errors at either the first equal sign or the second. What am I missing?
The branches of a case expression can only return values, not additional expressions to be evaluated in the where condition. You could, however, simulate this behavior with the and and or logical operators:
select *
from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where (ScheduleDate = testdate) and
((HF.IsHoliday = 1 and overtime = 1 and makeup = 0) or
(overtime = 0 and Makeup = 0)) and
DOW = 5
order by ActivityStartTime
Note that you have makeup = 0 on both branches of the case expression in the question (or both sides of the or in the answer), so you could extract it out of it and simplify the condition a bit:
select *
from ##ScheduleDetail SD
left join ##HolidayFilterTbl HF on SD.Scheduledate = HF.Testdate
where ScheduleDate = testdate and
makeup = 0 and
((HF.IsHoliday = 1 and overtime = 1) or
overtime = 0) and
DOW = 5
order by ActivityStartTime
If you are still wanting to know how to utilize a CASE Statement Expression in a WHERE Clause the CASE Expression must be compared to a value as that is the syntax understood for conditions contained within a WHERE Clause. See below a mock example.
SELECT *
FROM ##ScheduleDetail SD
LEFT JOIN ##HolidayFilterTbl HF ON SD.Scheduledate = HF.Testdate
WHERE(ScheduleDate = testdate)
AND
/* If you wish to stick with using a CASE Expression within the WHERE Clause set the the CASE Expression equal to 'something'. I usually stick with 1 or 0 'true/false'.
| You simply have to create your own True/False evaluation. You can add your logic checks within a CASE Expression within
| the WHERE Clause and when your logic is TRUE THEN return 1. Basically you are saying when 1 = 1 then return Record.
*/
1 =
Case
WHEN HF.IsHoliday = 1 AND makeup = 0 THEN
CASE WHEN (overtime = 1 OR overtime = 0) THEN 1 END /* Return 1 here to evaluation to TRUE */
ELSE
0 /* You can add another CASE here if needed and when the condition you write in evaluations to 1 'true' return record */
END
AND
DOW = 5
ORDER BY ActivityStartTime;
There are a few reasons I've used CASE Expressions within a WHERE Clause over using AND/ORs. Just one minor reason is it allows me to contain and organize logic in a WHERE Clause inside CASE Expressions rather than having multiple AND/ORs all nested together. I've also found that using CASE Expressions in the WHERE Clause is useful when encountering Dynamic queries that accept variables to be later inserted into the SQL before being sent to the database for processing. In the case of using Dynamic SQL there are times when a CASE Statement MUST be used due to the fact that there could be data that is being compared against in the WHERE clause that is NOT a column.field value but a hardcoded value that is compared to perhaps a user selection or status (as examples)... it might be a static value passed in via the application which is how my web application works that I support which is why I bring it up.
Basically it's good to know how to use a CASE Expression in a WHERE Clause as there are some cases when the ONLY way to evaluate certain data is by using a CASE Expression .
I have no data to test this against and that's not the point. The point of my answer is to simply provide to you an alternative to the existing answer. In my opinion this logic is basic and the already provided answer is the correct one however my answer is to demonstrate how you could go about using a CASE in a WHERE Clause.
If interested see this SO Post for the differences between a CASE Statement vs a CASE Expression however know that this terminology slightly differs between databases.
As an example of this... SQL Server refers to these as Simple vs Searched but refers to all of it as a CASE Expression. Therefore a CASE Expression can either be a Simple or a Searched CASE that can be used within a Statement.

Where clause, multiple sets of conditions

I am trying to produce a single table query result with error payment data filtered out by the conditions below. I am unable to get the query to filter out all of the sets of conditions, only the first 3. I have tried different ordering as well as making the last two condition sets a sub-query.
How can I filter out all the below conditions?
Again, 1,2 and 3 seem to have the desired result.Conditions 4 and 5 function, just not when following conditions 1,2 and 3
select [history].[id]
[history].[trans],
CAST([history].[paid_dt] AS Date),
CAST([history].[due_dt] AS Date),
FROM [history]
LEFT OUTER JOIN [information] ON [history].[id] = [information].[id]
--Condition 1--
WHERE NOT ([history].[trans] IN
('TRSF',
'TRR',
'BEG',
'DTR',
'LTC',
))
OR
--Condition 2--
(CONVERT(date,[paid_dt]) = '2015-12-30'
AND [trans] = 'ADJE')
OR
-- Condition 3--
([history].[paid_dt] = [information].[date]
AND [history].[trans] LIKE '%ADJE%'
AND [history].[due_dt] < '2017-01-01')
--Condition 4--
OR
(datepart(dd, [paid_dt]) = 8)
--assume there is more to this condition--
OR
--Condition 5--
(CONVERT(date,[history].[paid_dt]) = '2018-01-08'
and [history].[trans] = 'MANR'));
Just looking for insight as how to address
'NOT' acts only on one condition. If you don't want any of the other conditions to be returned if true... try surrounding all conditions following the 'NOT' keyword in parentheses. Also, double check where you have your parentheses. I'm still seeing an odd number of those maybe due to pasting.
WHERE NOT
(
(Condition 1)
OR
(Condition 2)
)
You can also try getting away from the 'NOT' keyword by using <> references instead.

Gettin a value from a table and using in the same query

SELECT (h.horario), h.codigo
FROM horarios as h
JOIN horario_turma as h_t
ON(h.codigo != h_t.cd_horario)
WHERE h_t.cd_turma = 'HTJ009'
AND h_t.cd_dia = 2
AND h.cd_turno = 1
I'm trying to figure out if there's a possibility to get the h.cd_turnovalue from another table and use in the same query, beacuse this value is gonna be variable. So, I'd have to get this value from a query, then pass the value to PHP and do another query with this value. Is there a way to do that in the same query?
There's a table called turmas(codigo, cd_turno). I'll have the codigovalue, in this case HTJ009, and I'd like to select the cd_turno value.
Query used to get the value:
SELECT cd_turno FROM turmas WHERE codigo='HTJ009'
You can use a subquery, like so:
SELECT (h.horario), h.codigo
FROM horarios as h
JOIN horario_turma as h_t
ON(h.codigo != h_t.cd_horario)
WHERE h_t.cd_turma = 'HTJ009'
AND h_t.cd_dia = 2
AND h.cd_turno = (SELECT cd_turno FROM turmas WHERE codigo='HTJ009')
In this case, remember that it is important for the subquery to return only one result, otherwise you'll encounter an error. If you do see such an error, you may have to tweak the subquery to ensure only one result is returned.
Check this out for Postgres subquery documentation
SELECT (h.horario), h.codigo
FROM horarios as h
JOIN horario_turma as h_t
ON(h.codigo = h_t.cd_horario)
WHERE h_t.cd_turma = 'HTJ009'
AND h_t.cd_dia = 2
AND h.cd_turno = 1 and h_t.cd_horario is null

Nz() not working in MS Access

I have a cross tab query that is counting Patient_ID's as the value.
Total = Nz(Count(Research.Patient_ID))+0
I have also tried:
Total = Nz(Count(Research.Patient_ID)
and....
Total = Nz(Count(Research.Patient_ID, 0)
etc. Nz() only works if at least one value is not null. However, if all of them are null, instead of seeing all 0's, I see nothing.
This is problematic because I am using these queries as subqueries. The main query takes the values from this one (and others like it) and adds them together. Unfortunately, if one of the subqueries is entirely null, then the sum actually turns up null, regardless of whether or not should be.
For example:
subquery1: Nz(Count(Research.Patient_ID))+0
subquery2: Nz(Count(Research.All_ID))+0
mainquery: subquery1 + subquery2
if subquery1 = 4, and subquery2 = Null...
mainquery = subquery1 + subquery2
mainquery = Null
when really...
mainquery = 4
Please help.
In this query, the main query produces the sum of counts determined in two subqueries. Is this what you're after?
SELECT
Nz(s1.CountOfPatient_ID,0) + Nz(s2.CountOfAll_ID,0)
FROM
[SELECT Count(Patient_ID) AS CountOfPatient_ID FROM Research]. AS s1,
[SELECT Count(All_ID) AS CountOfAll_ID FROM Research]. AS s2
nz(null, null)+0 will always be null as null + anything is null.
If nz() can return null, just apply another nz() to handle it;
SELECT ... nz(nz([value1], [value2]), 0)
You should probably be more elaborate and post the exact part of your main query where the two counts are being added up.
So far I can only guess that you need to add NZ() to the main query expression, something like (using your pseudo-code)
mainquery = NZ(subquery1, 0) + NZ(subquery2, 0)

Filter for NULL in list

why does filter for NULL in subqueries does not work?
I hoped to get the correct result by add NULL to the list of allowed values, for example:
SELECT ERP_ServiceProcess.fiStatusNew, RMA.IdRMA
FROM ERP_ServiceProcess RIGHT OUTER JOIN
RMA ON ERP_ServiceProcess.fiRMA = RMA.IdRMA
WHERE (ERP_ServiceProcess.fiStatusNew IN (NULL, 1, 7, 8))
order by ERP_ServiceProcess.fiStatusNew
This gives the incorrect result because all records in RMA that have no records in sub-table ERP_ServiceProcess(where ERP_ServiceProcess.fiStatusNew IS NULL) are dropped.
I must use this (slow) query to get the correct result:
SELECT ERP_ServiceProcess.fiStatusNew, RMA.IdRMA
FROM ERP_ServiceProcess RIGHT OUTER JOIN
RMA ON ERP_ServiceProcess.fiRMA = RMA.IdRMA
WHERE (ERP_ServiceProcess.fiStatusNew IS NULL)
OR (ERP_ServiceProcess.fiStatusNew IN (1, 7, 8))
order by ERP_ServiceProcess.fiStatusNew
Why do i have to use the second, slow query although i used RIGHT OUTER JOIN and i've added NULL to the subquery?
Thank you in advance.
It doesn't work as you expect as it gets expanded to a bunch of equals operations
fiStatusNew = NULL OR fiStatusNew = 1 OR fiStatusNew = 7 OR fiStatusNew = 8
and anything = NULL is unknown.
Given this expansion there's no particular reason to think that adding an additional OR using IS NULL would make things slower on its own (the additional predicate might change the query plan to use a different access path if the statistics lead it to belive that the number of matching rows warrants this though)
You see the same behaviour in the CASE operation
SELECT CASE NULL WHEN NULL THEN 'Yes' ELSE 'No' END /*Returns "No"*/
This is one reason why you should take particular care with the inverse operation NOT IN. If the list contains any NULL values you will always get an empty result set.
fiStatusNew NOT IN (NULL, 1,2)
Would expand to
fiStatusNew<> NULL and fiStatusNew<> 1 and fiStatusNew<> 2
or
Unknown And True/False/Unknown And True/False/Unknown
Which always evaluates to Unknown under three valued logic.
Could you try using
ISNULL(ERP_ServiceProcess.fiStatusNew,0) IN (0, 1, 7, 8)
Untested but might be quicker than the 2nd query.
'ERP_ServiceProcess.fiStatusNew IN (NULL)' evaluates to 'ERP_ServiceProcess.fiStatusNew = NULL' and that always is false. NULL is defined in sql server as 'unknown', not as 'no value'. That's why NULL = NULL or NULL = #var (*) always evaluates to false. If you have two unknowns, you cannot check if they are equal. Only 'is NULL' works.
(*) Well, for sql server, you can set ANSI_NULLS to off but that's not really recommended as it is not standard sql behaviour.