Oracle SQL ignores condition in WHERE clause - sql

I have this simple part of SQL query
where aia.invoice_num in (:invoice_num) or aia.invoice_num is null
and ipa.payment_date between (:start_date) and (:end_date) or ipa.payment_date >= (:start_date) or (:start_date is null and :end_date is null)
and ipa.PAYEE_NAME in (:payee) or :payee is null
I have 4 parameters, invoice_num, start_date, end_date and Payee, I want it to be just like a filter, If one of the conditions above is present then it must be applied, if not present then it must be ignored, but it just doesn't work as expected, if I pass invoice_num the result will be all the invoices anyway whether other parameters are present or null, how can I force every condition if present and make it ignored if null ?

Your query does not work because:
AND has a higher operator precedence than OR which means it is evaluated as:
where ( aia.invoice_num in (:invoice_num) )
or ( aia.invoice_num is null
and ipa.payment_date between (:start_date) and (:end_date) )
or ( ipa.payment_date >= (:start_date) )
or ( :start_date is null
and :end_date is null
and ipa.PAYEE_NAME in (:payee) )
or ( :payee is null )
so if any of the OR conditions is true then the rest can be ignored.
You compare aia.invoice_num is null rather than :invoice_num IS NULL.
To fix it, you can use:
WHERE ( aia.invoice_num = :invoice_num OR :invoice_num IS NULL )
AND ( ipa.payment_date >= :start_date OR :start_date IS NULL )
AND ( ipa.payment_date <= :end_date OR :end_date IS NULL )
AND ( ipa.PAYEE_NAME = :payee OR :payee IS NULL )

Related

Combine two selects

I have a problem with two sql querys.
The one sql selects some ID's and the other one sets the id structur.
The problem is I can't get them both to work as one query.
The SQL which sets the structure:
select nstrid
from t_ousernstr
where kstrid = 116 And
Bis is null
Order by nstrid
The id's from that are like:
100
200
300
400
And the SQL which gets the user id's:
SELECT
T_OUSER.ID AS ID,
FROM
T_OUSER,
T_OUSERNSTR
WHERE
( T_OUSERNSTR.NSTRID = ANY(//here should be the id's from above))
(T_OUSERNSTR.VON is null or SYSDATE >=T_OUSERNSTR.VON) and
(T_OUSERNSTR.BIS is null) and
(T_OUSERNSTR.BEGINN IS NULL OR T_OUSERNSTR.BEGINN<= SYSDATE) and
(T_OUSERNSTR.ENDE is null or T_OUSERNSTR.ENDE> SYSDATE)
Order By T_OUSER.ID;
Use IN:
SELECT o.ID AS ID
FROM T_OUSER o
CROSS JOIN
T_OUSERNSTR n
WHERE n.NSTRID IN ( select nstrid
from t_ousernstr
where kstrid = 116
And Bis is null )
AND ( n.BIS IS NULL )
AND ( n.VON IS NULL OR SYSDATE >= n.VON )
AND ( n.BEGINN IS NULL OR SYSDATE >= n.BEGINN )
AND ( n.ENDE IS NULL OR SYSDATE < n.ENDE )
ORDER BY o.ID;
or EXISTS:
SELECT o.ID AS ID
FROM T_OUSER o
CROSS JOIN
T_OUSERNSTR n
WHERE EXISTS (
SELECT 1
FROM t_ousernstr x
WHERE x.kstrid = 116
AND x.Bis IS NULL
AND ( n.NSTRID = x.NSTRID OR ( n.NSTRID IS NULL AND x.NSTRID IS NULL ) )
)
AND ( n.BIS IS NULL )
AND ( n.VON IS NULL OR SYSDATE >= n.VON )
AND ( n.BEGINN IS NULL OR SYSDATE >= n.BEGINN )
AND ( n.ENDE IS NULL OR SYSDATE < n.ENDE )
ORDER BY o.ID;
or to remove the correlated sub-query you could use analytic functions:
SELECT o.ID AS ID
FROM T_OUSER o
CROSS JOIN
( SELECT n.*,
MAX( CASE WHEN kstrid = 116 THEN 1 ELSE 0 END )
OVER ( PARTITION BY bis, nstrid )
AS has_kstrid
FROM T_OUSERNSTR n
) n
WHERE n.has_kstrid = 1
AND ( n.BIS IS NULL )
AND ( n.VON IS NULL OR SYSDATE >= n.VON )
AND ( n.BEGINN IS NULL OR SYSDATE >= n.BEGINN )
AND ( n.ENDE IS NULL OR SYSDATE < n.ENDE )
ORDER BY o.ID;

How to exclude negative values in resul

Please how can I get this query to exclude negative (-) values
SELECT Enrollment.Participant_ID
,Enrollment.Site
,Enrollment.ActualDelivery
,Forms.[2MonthQoL]
,[Enrollment].[ActualDelivery] + 70 AS Due
,DateDiff("d", [Due], DATE ()) AS DaysOverdue
FROM Enrollment
LEFT JOIN Forms ON Enrollment.Participant_ID = Forms.Participant_IDFK
WHERE (
((Enrollment.ActualDelivery) IS NOT NULL)
AND ((Forms.[2MonthQoL]) IS NULL)
);
You can add the condition to the where clause:
WHERE Enrollment.ActualDelivery) IS NOT NULL AND
Forms.[2MonthQoL]) IS NULL AND
DateDiff("d", [Due], DATE()) >= 0
This would be more naturally written as:
WHERE Enrollment.ActualDelivery) IS NOT NULL AND
Forms.[2MonthQoL]) IS NULL AND
[Due] <= DATE()
You can use function ABS() to get the absolute value of a number like:
SELECT Enrollment.Participant_ID
,Enrollment.Site
,Enrollment.ActualDelivery
,Forms.[2MonthQoL]
,[Enrollment].[ActualDelivery] + 70 AS Due
,ABS(DateDiff("d", [Due], DATE ())) AS DaysOverdue
FROM Enrollment
LEFT JOIN Forms ON Enrollment.Participant_ID = Forms.Participant_IDFK
WHERE (
((Enrollment.ActualDelivery) IS NOT NULL)
AND ((Forms.[2MonthQoL]) IS NULL)
);
If you just want those negatives to be NULL you can use an IIF():
SELECT Enrollment.Participant_ID
,Enrollment.Site
,Enrollment.ActualDelivery
,Forms.[2MonthQoL]
,[Enrollment].[ActualDelivery] + 70 AS Due
,IIF((DateDiff("d", [Due], DATE ())<0, NULL, (DateDiff("d", [Due], DATE ())) AS DaysOverdue
FROM Enrollment
LEFT JOIN Forms ON Enrollment.Participant_ID = Forms.Participant_IDFK
WHERE (
((Enrollment.ActualDelivery) IS NOT NULL)
AND ((Forms.[2MonthQoL]) IS NULL)
);

Specified Twice Table for 'DELETE' in MariaDB

I created a query to delete some record in MariaDB
Query :
DELETE
FROM
HrAttLogsFormatted
WHERE
DateIn = '2019-04-10'
AND Late != ''
AND ( FingerId, CreatedDate ) IN (
SELECT
FingerId,
MAX( CreatedDate )
FROM
HrAttLogsFormatted
WHERE
DateIn = '2019-04-10'
AND Late != ''
AND FingerId IN ( SELECT FingerId FROM HrAttLogsFormatted WHERE DateIn = '2019-04-10' AND Late != '' GROUP BY FingerId HAVING COUNT( FingerId ) > 1 )
GROUP BY
FingerId
)
Result :
Table 'HrAttLogsFormatted' is specified twice, both as a target for
'DELETE' and as a separate surce for data
But with the query I made unsuccessfully, is there a way to solve it?
Thank you in advance
[EDIT-SOLVED] It's Solved with simply apply and query
DELETE t1
FROM HrAttLogsFormatted t1
INNER JOIN
(
SELECT FingerId, MinCreatedDate
FROM
(
SELECT FingerId, MIN(CreatedDate) AS MinCreatedDate
FROM HrAttLogsFormatted
WHERE DateIn = '2019-05-03' AND Late != ''
GROUP BY FingerId HAVING COUNT(FingerId) > 1
) x
) t2
ON t1.FingerId = t2.FingerId AND t1.CreatedDate = t2.MinCreatedDate;
I would try writing this as a delete join:
DELETE t1
FROM HrAttLogsFormatted t1
INNER JOIN
(
SELECT FingerId, MIN(CreatedDate) AS MinCreatedDate
FROM HrAttLogsFormatted
WHERE DateIn = '2019-04-10' AND Late != ''
GROUP BY FingerId
HAVING COUNT(FingerId) > 1
) t2
ON t1.FingerId = t2.FingerId AND t1.CreatedDate = t2.MinCreatedDate;
If you really wanted to stick with your current query, you might be able to make it work by adding an additional subquery around the WHERE IN clause:
AND (FingerId, CreatedDate) IN (
SELECT FingerId, MinCreatedDate
FROM
(
SELECT FingerId, MIN(CreatedDate) AS MinCreatedDate
FROM HrAttLogsFormatted
...
) x )
But, I would use the version I gave, because it is simpler.

Display two count from a single in two different column from a single table

I have a table where I record daily work of employees. I have a query where I display the current work for today for each employee and have another query where I display the total count of work for each employee.
I want to combine the 2 queries into a single one where I have a daily column and a cumulative column.
my query is below:
SELECT staff,
process_inprogress,
not_yet_completed
FROM (SELECT staff,
Count(number) AS Process_InProgress,
Count(team_name) AS Not_Yet_Completed
FROM dbo.empty_shell_workflow
WHERE ( end_date IS NULL )
AND ( process_name IS NOT NULL )
AND ( billing_amount IS NULL )
AND ( deletion IS NULL )
AND ( team_name = 'Team Vishma' )
AND ( CONVERT(DATE, start_date) = CONVERT(DATE, Getdate()) )
GROUP BY staff
UNION ALL
SELECT staff,
Count(number) AS Process_InProgress,
Count(team_name) AS Not_Yet_Completed
FROM dbo.empty_shell_workflow AS Empty_Shell_Workflow_1
WHERE ( team_name = 'Team Vishma' )
AND ( billing_amount IS NULL )
AND ( tag_number IS NULL )
AND ( initiator IS NOT NULL )
AND ( end_date IS NULL )
AND ( deletion IS NULL )
AND ( process_name IS NOT NULL )
GROUP BY staff) AS t
however it is being display only in a single column for both daily and cumulative
Below is how i want it to display
Staff Process_Progress(Daily) Not_YetCompleted(Cumulative)
A 2 5
B 0 1
C 6 8
however from the query above, the cumulative is being display in the daily column
Any idea, how can I modify the query?
you could try like below by using case when
with cte as
( SELECT staff,CONVERT(DATE, start_date) as date_of_month
Count(number) AS Process_InProgress
FROM dbo.empty_shell_workflow AS Empty_Shell_Workflow_1
WHERE ( team_name = 'Team Vishma' )
AND ( billing_amount IS NULL )
AND ( tag_number IS NULL )
AND ( initiator IS NOT NULL )
AND ( end_date IS NULL )
AND ( deletion IS NULL )
AND ( process_name IS NOT NULL )
GROUP BY staff,CONVERT(DATE, start_date)
) select staff, sum(case when date_of_month = CONVERT(DATE, Getdate()) then
Process_InProgress else 0 end) as Process_Progress_Daily,
sum(case when date_of_month != CONVERT(DATE, Getdate()) then
Process_InProgress else 0 end) as Not_YetCompleted
from cte
group by staff

TSQL - Multiple aliases for CASE WHEN statement

I have a query that selects columns from a table where the condition is met, the problem is this logic is repeated several times (once for each column required) and wondered if there was a better way of doing it.
SELECT
CASE
WHEN (date1 IS NULL) THEN [date2]
WHEN (date1 IS NOT NULL OR ( date1 IS NOT NULL AND date2 IS NOT NULL )) THEN [date1]
ELSE ''
END AS selectedDate
//Repeat above statement for [day], [hour], [minute]
I want to know if its possible to aggregate a number of these case statements under the same statement with separate aliases as they all rely on the same conditions instead of rewriting the same statement multiple times for each column, for example I tried the following:
SELECT
CASE
WHEN (date1 IS NULL) THEN [date2] as "selectedDate", [day2] as "day", [hour2] as "hour", [minute2] as "minute"
WHEN (date1 IS NOT NULL OR ( date1 IS NOT NULL AND date2 IS NOT NULL )) THEN [date1] as "selectedDate", [day1] as "day", [hour1] as "hour", [minute1] as "minute"
ELSE ''
Not in the way you are describing...
An alternative would be to use isnull() or coalesce():
select
SelectedDate = coalesce(date1,date2)
, [Day] = coalesce(day1,day2)
, [Hour] = coalesce(hour1,hour2)
, [Minute] = coalesce(minute1,minute2)
from t
No. Each column needs its own select statement.
For your particular application of this CASE statement, you could be using COALESCE instead.
SELECT COALESCE(date1, date2) AS selectedDate FROM SomeTable