Can't explain this SQL query - sql

Im sure these kind of questions are frowned upon but I really need some help. For the past 3 hours I have been staring at this SQL query and I just can't explain some of the logic in it. Normally I wouldn't ask but I'm reaching a deadline.
In the WHERE clause you will see an If construction. From what I can see it checks whether or not the Picking date was valid.
However, the way it's phrased it just looks weird, doesnt it always result in a 'Between'? (If x > y AND x < z then 'Between', else 'Not Between) = 'Between'.
And on what object does this 'if' result apply too? The way I interpret it the end result becomes WHERE 'Between' AND 'Between', which just doent make sense...
Any help is appreciated (P.S. The query is written for Access)
SELECT
DWH_PickOrderLines_Temp.*,
IIf(DWH_PickOrderLines_Temp.WayOfTransport IN ("ON", "PD"), "Kitting " & Mid(tbl_District_Activiteit.Activiteit, 8), IIf(DWH_PickOrderLines_Temp.PickMethode IN ("K", "V"), "Picking Bulk", tbl_District_Activiteit.Activiteit)) AS Activiteit,
IIf(DWH_PickOrderLines_Temp.WayOfTransport IN ("ON", "PD"), "Kitting", tbl_District_Activiteit.[Activiteit groep]) AS [Activiteit groep],
R14_Distinct_Warehouse_Location.Proces,
R14_Distinct_Warehouse_Location.Gebouw
FROM DWH_PickOrderLines_Temp
LEFT JOIN R14_Distinct_Warehouse_Location
ON DWH_PickOrderLines_Temp.PickLocation = R14_Distinct_Warehouse_Location.PickLocation
WHERE (((IIf([DWH_PickOrderLines_Temp].[PickDateTime] >= [R14_Distinct_Warehouse_Location].[tbl_Location_Zone_District.ValidFrom]
AND [DWH_PickOrderLines_Temp].[PickDateTime] < [R14_Distinct_Warehouse_Location].[tbl_Location_Zone_District.ValidTo], "Between", "Not Between")) = "Between")
AND ((IIf([DWH_PickOrderLines_Temp].[PickDateTime] >= [R14_Distinct_Warehouse_Location].[tbl_District_Activiteit.ValidFrom]
AND [DWH_PickOrderLines_Temp].[PickDateTime] < [R14_Distinct_Warehouse_Location].[tbl_District_Activiteit.ValidTo], "Between", "Not Between")) = "Between"));

the where never returns a value. and it is duplicated....
declare #pickdate int = 1
declare #validForm int = 0
print 'start'
if(((IIf(#pickdate >= #validForm AND #pickdate < #validForm, 'Between', 'Not Between')) = 'Between')
AND ((IIf(#pickdate >= #validForm AND #pickdate < #validForm, 'Between', 'Not Between')) = 'Between'))
print 'test'

I think the query miss a part (references to two tables, see my comment above). Anyway I think you can simplify where condition:
WHERE [DWH_PickOrderLines_Temp].[PickDateTime] >= [R14_Distinct_Warehouse_Location].[tbl_Location_Zone_Distric‌​t.ValidFrom]
AND [DWH_PickOrderLines_Temp].[PickDateTime] < [R14_Distinct_Warehouse_Location].[tbl_Location_Zone_Distric‌​t.ValidTo]
AND [DWH_PickOrderLines_Temp].[PickDateTime] >= [R14_Distinct_Warehouse_Location].[tbl_District_Activiteit.V‌​alidFrom]
AND [DWH_PickOrderLines_Temp].[PickDateTime] < [R14_Distinct_Warehouse_Location].[tbl_District_Activiteit.V‌​alidTo]

Why do you think if statement always results in 'Between'?
Basically, where condition boils down to:
where
pickDateTime between validFrom1 and validTo1
and
pickDateTime between validFrom2 and validTo2

Related

Where statement in my query is supposed to return only today's and yesterday's dates, but is still returning earlier dates

I am looking to only retrieve data from the past 24 hours. The WHERE statement I am using, in theory, should retrieve only from those productiondates. However, I am still having week-old productiondates returned. Any thoughts on how to improve this, or am I doing it wrong? I am using periscope.
select example1,
example2,
example3,
productiondate,
example4,
example5
from final
where exampleX = exampleY or exampleX is null
and productiondate > DATEADD(day,-1, GETDATE())
and example1 <> 'XXX'
and example2 <> 'YYY'
and example2 <> 'ZZZ'
order by 2
Logical operator precedence in SQL can be surprising. You need parentheses around the OR.
where (exampleX = exampleY or exampleX is null)
Alternatively, you could do this:
where coalesce(exampleX, exampleY) = exampleY

R equivalent of case when in SQL?

I have been using T-SQL for a while but I now have to make transition to R...
select case when date_column_1 < '20160801' then date_column_1 else '20160801' end as date_column_1, case when date_column_2 < '99991231' then '20190701' else date_column_2 end as date_column_2 from table
Also, apologies in advance with my crappy stackoverflow formatting skills.
Since you have only one condition to check for each column, we can use ifelse here. If there are multiple conditions you could check case_when from dplyr.
transform(table, date_column_1 = ifelse(date_column_1 < as.Date('2016-08-01'),
date_column_1, as.Date('2016-08-01')),
date_column_2 = ifelse(date_column_2 < as.Date('9999-12-31'),
as.Date('2019-07-01'), date_column_2))
Assuming date_column_1 and date_column_2 are of Date class, you cannot directly compare dates with literal string ("20160801") in R, so we convert the dates to compare to Date class as well. Moreover, for date_column_2 do you mean to replace all values with the date "2019-07-01" ?
As mentioned by #G. Grothendieck ifelse would convert the dates to numeric. We can use if_else from dplyr which is type-strict and will maintain the dates.
library(dplyr)
table %>%
mutate(date_column_1 = if_else(date_column_1 < as.Date('2016-08-01'),
date_column_1, as.Date('2016-08-01')),
date_column_2 = if_else(date_column_2 < as.Date('9999-12-31'),
as.Date('2019-07-01'), date_column_2)))

Redshift Correlated Subquery Internal Error

So I have a table of bids in Amazon Redshift. Each bid has a description and a user who made the bid, and for each bid I want to know if a user made a bid with the same description in the last 5 days.
The query looks like this:
select b1.bid_id, case when
exists(select b2.bid_id from dim_bid b2 WHERE b1.user_id = b2.user_id
and b2.bid_timestamp < b1.bid_timestamp and b2.bid_timestamp > b1.bid_timestamp - INTERVAL '5 day'
and b2.description = b1.description and b2.bid_timestamp > '2017-04-25') then 'good bid' else 'duplicate bid' END
from dim_bid b1
where b1.hidden
which doesn't work, giving the error: this type of correlated subquery is not supported due to internal error. However when I just add a "=True" at the end it works.
select b1.bid_id, case when
exists(select b2.bid_id from dim_bid b2 WHERE b1.user_id = b2.user_id
and b2.bid_timestamp < b1.bid_timestamp and b2.bid_timestamp > b1.bid_timestamp - INTERVAL '5 day'
and b2.description = b1.description and b2.bid_timestamp > '2017-04-25') then 'good bid' else 'duplicate bid' END
from dim_bid b1
where b1.hidden = True
Is this just a bug, or is there some deep reason why the first one can't be done?
I think the better way to write the query uses lag():
select b.*,
(case when lag(b.bid_timestamp) over (partition by b.description order by b.timestamp) > b.bid_timestamp - interval '5 day'
then 'good bid' else 'duplicate bid'
end)
from dim_bid b;
Try to run this first:
select b1.bid_id
from dim_bid b1
where b1.hidden
You will see that redshift will raise a different error(eg. WHERE must be type boolean...). So argument of where must be a boolean in order for the query to run. So when you add '=True' then argument is boolean and query runs. And when the query has correlated subquery and there is an invalid operation in the query I have noticed that redshift raises correlated subquery error. This might be due to the fact that redshift does not support some of the correlated subqueries(correlated subqueries redshift).
The docs state the following:
We recommend always checking Boolean values explicitly, as shown in the examples following. Implicit comparisons, such as WHERE flag or WHERE NOT flag might return unexpected results.
Reference: http://docs.aws.amazon.com/redshift/latest/dg/r_Boolean_type.html
I do not think this is necessarily a bug. I would recommend always checking boolean values as where b1.hidden is True. I have seen this error quite a few times when using correlated subqueries, but I have always been able to fix it when explicitly checking the boolean values using is true/false/unknown.

Decode with AND clause oracle

I want to use parameter in my query but I can't handle with it
I have 3 big selects to raport and I just want to use parameter for some part of code which depends from choice
I have 3 different Where conditions
1st
..WHERE A.CANCELLED = 'FALSE' AND a.open_amount!=0 AND A.IDENTITY = '&client_id'..
2nd
...WHERE A.CANCELLED = 'FALSE' AND A.IDENTITY = '&client_id' ...
3rd
WHERE AND A.CANCELLED = 'FALSE' AND a.invoice_amount != a.open_amount AND A.IDENTITY = '&client_id'
I tried with decode but I guess it could be ok if there would be value in 2nd case but there isn't and I cant decode like this
WHERE decode(xxx,x1,'AND a.open_amount!= 0',x2,'',x3, 'AND a.invoice_amount != a.open_amount')
How I should solve that problem any tips?
Do you mean, if the first "where condition" OR the second OR the third is/are TRUE, you want the overall to be TRUE (select the row), and you are looking for a simplified way to write it? That is, without simply combining them with OR?
To achieve that, you don't need CASE and nested CASE statements or DECODE. You could do it like this:
WHERE A.CANCELLED = 'FALSE'
AND A.IDENTITY = '&client_id'
AND ( (xxx = x1 AND a.open_amount != 0) OR (xxx = x2) OR
(xxx = x3 AND a.invoice_amount != a.open_amount) )
This is more readable, the intent is clear, it will be easier to modify if needed, ...
You can try something like -
WHERE A.CANCELLED = 'FALSE'
AND A.IDENTITY = '&client_id'
AND a.open_amount <>
(CASE
WHEN x1 THEN 0
WHEN x2 THEN a.open_amount + 1 -- This needs to be something that is always TRUE, to nullify the condition
WHEN x3 THEN a.invoice_amount
END);
Edit: This is based on the assumption that a.open_amount is a NUMBER and uses a quick hack where we create an always TRUE condition like x <> x + 1. You should probably change this to whatever suits you better based on your data.

SQL check for NULLs in WHERE clause (ternary operator?)

What would the SQL equivalent to this C# statement be?
bool isInPast = (x != null ? x < DateTime.Now() : true)
I need to construct a WHERE clause that checks that x < NOW() only if x IS NOT NULL. x is a datetime that needs to be null sometimes, and not null other times, and I only want the WHERE clause to consider non-null values, and consider null values to be true.
Right now the clause is:
dbo.assignments.[end] < { fn NOW() }
Which works for the non-NULL cases, but NULL values always seem to make the expression evaluate to false. I tried:
dbo.assignments.[end] IS NOT NULL AND dbo.assignments.[end] < { fn NOW() }
And that seems to have no effect.
For use in a WHERE clause, you have to test separately
where dbo.assignments.[end] is null or dbo.assignments.[end] < GetDate()
or you can turn the nulls into a date (that will always be true)
where isnull(dbo.assignments.[end],0) < GetDate()
or you can do the negative test against the bit flag derived from the below
where case when dbo.assignments.[end] < GetDate() then 0 else 1 end = 1
The below is explanation and how you would derive isInPast for a SELECT clause.
bool isInPast = (x != null ? x < DateTime.Now() : true)
A bool can only have one of two results, true or false.
Looking closely at your criteria, the ONLY condition for false is when
x != null && x < now
Given that fact, it becomes an easy translation, given that in SQL, x < now can only be evaluated when x!=null, so only one condition is needed
isInPast = case when dbo.assignments.[end] < { fn NOW() } then 0 else 1 end
(1 being true and 0 being false)
Not sure what { fn NOW() } represents, but if want SQL Server to provide the current time, use either GETDATE() or if you are working with UTC data, use GETUTCDATE()
isInPast = case when dbo.assignments.[end] < GetDate() then 0 else 1 end
The one you are looking for is probably the CASE statement
You need something like
WHERE X IS NULL
OR X < NOW()
Have two separate queries, one when x is null one when is not. Trying to mix the two distinct conditions is the sure shot guaranteed way to get a bad plan. Remember that the generated plan must work for all values of x, so any optimization based on it (a range scan on an index) is no longer possible.