Why is this "where" clause not limiting sql results - mysql

I'm trying to limit results in a table to records with dates that don't overlap my data. As you can see in the screenshot below I'm trying to add a clause to filter out records that are equal to the "end" column. See the final line in the query for that.
I can't figure out why results still show the record in the screenshot. Can someone help me out explaining that? It's probably a syntax thing?

You basically have:
a OR b AND c AND d AND e AND f
... and you probably want:
(a OR b) AND c AND d AND e AND f
Reference: Operator Precedence

AND has a higher operator precedence than OR has.
That means that your AND clauses will be interpreted first so that at the end there's something like
where (...) or (... and ... and ...)
Since the first condition before the OR (('2014-01-14 18:30:00' between start and end)) is met, your row shows up. Put both sides of the OR clause in parantheses and it should work as you want to.

The problem is the first part of your WHERE clause is passing that record. I believe you need to more your brackets around a bit.
I'm not completely sure on what you are trying to achieve with the data that you have provided, but an opening bracket after the OR keyword and a closing bracket right at the end should do it.
Like this:
where
('2014-01-14 18:30:00' between start and end)
or (('2014-01-14 19:30:00' between start and end)
and ('2014-01-14 18:30:00' != start)
and ('2014-01-14 19:30:00' != end)
and ('2014-01-14 19:30:00' != start)
and ('2014-01-14 18:30:00' != end))

Because 2014-01-14 18:30 is between 2014-01-14 16:00 and 2014-01-14 18:30 which is a TRUE condition. And [(TRUE) Or (whatever else)] is also TRUE

Related

SQL CASE Statement Error while checking conditions

The scenario is that i have two columns one is Quantity and other is Type. Now what i am trying to do is check if type is "rec" then it take all the values from quantity and add them and if the type is "issue" then it will get only those fields whose type is receiving and add them all on the basis of ITEM ID. The SQL Query i have written is here:
SELECT f.`Itemm_ID`,ABS(SUM(f.`Quantity`)) AS recieving, TYPE ,
(CASE
WHEN f.`Type` = 'issue'
THEN ABS(SUM(f.`Quantity`))
END)
FROM stock_journal AS f
WHERE f.`Itemm_ID`='1'
Now the thing is everything is working fine except CASE statement which is returning null.
Please help me in resolving my issue. Thank you
It seems that you need in
SELECT f.`Itemm_ID`,
ABS(SUM(f.`Quantity`)) AS recieving,
TYPE,
ABS(SUM(CASE WHEN f.`Type` = 'issue'
THEN f.`Quantity`
ELSE 0
END))
FROM stock_journal AS f
WHERE f.`Itemm_ID`='1'
PS. Does f.Quantity may be negative? If not then ABS() is excess. If it may then ABS() must wrap inner f.Quantity, not the whole SUM(), maybe.
PPS. TYPE in output is formally incorrect (contradicts with ONLY_FULL_GROUP_BY), I'd recommend wrap it with ANY_VALUE().
i didn't get your recommendation of wrapping type with value can you please elaborate more.
I mean that (maybe, I'm not sure) you need
SELECT f.`Itemm_ID`,
SUM(ABS(f.`Quantity`)) AS recieving,
TYPE,
SUM(CASE WHEN f.`Type` = 'issue'
THEN ABS(f.`Quantity`)
ELSE 0
END)
FROM stock_journal AS f
WHERE f.`Itemm_ID`='1'
Have you checked syntax for CASE I think you are missing ELSE part in the query
Eg:-
SELECT OrderID, Quantity,
CASE
WHEN Quantity > 30 THEN "The quantity is greater than 30"
WHEN Quantity = 30 THEN "The quantity is 30"
ELSE "The quantity is under 30"
END
FROM OrderDetails;
check here for syntax

Having a Date And DateTime Comparison problem in my SQL

Been testing this over and over, and it fails at the date comparison.(item.id_type seems to work fine).
request.date has the datatype DATETIME.
SELECT request.id, request.date, request.total_price,
item.cod_GERFIP,item.price,item.name,request_item.quantity,
section.name AS section,user.firstname,user.lastname
FROM ((((`request_item`
INNER JOIN `request` ON request_item.id_request = request.id)
INNER JOIN `item` ON request_item.id_item = item.cod_GERFIP)
INNER JOIN `user` ON request.id_user = user.id)
INNER JOIN `section` ON user.section = section.id)
WHERE request.date >= '2019-01-09' AND request.date <= '2019-01-10'
AND item.id_type = '1'
ORDER BY request.date DESC
Just a guess, because you haven't explained what or how the query fails, but to my eyes this condition does not look correct:
request.date <= '2019-01-10'
It's a common mistake to expect a condition like this, when used a part of a range, to include all records where the date part of a datetime field is 2019-01-10. That is, if we have an example value in the database of 1 PM on the same day (2019-01-10 13:00:00), the expectation is this value will narrow to match the 2019-01-10 literal in the query, the two values will be equal, and so it will meet the condition.
It does work this way.
Instead, the 2019-01-10 literal in the query is widened to a full DateTime, that looks more like this: 2019-01-10 00:00:00.000. Now the 1 PM value from the table is compared with this full date time, and it fails the condition.
It's much more common for a date range to compare using an exclusive upper bound set for one day in the future:
request.date < '2019-01-11'
Alternatively, you may be tempted to do this:
request.date <= '2019-01-10 23:59:59.999'
It will even work most of the time. Just be warned that in the (rare) case of leap seconds, you can still end up with incorrect results that way.
You may also be tempted to do something like this:
convert(date,request.date) <= '2019-01-10'
This works, but it's not recommended because it prevents the use of any index you might have on the request.date field, and that cuts at the core of database performance.
Or maybe the problem is even simpler. With the start of range at 2019-01-09, maybe you wanted to get the records for exactly one day, and are surprised to see a few values from midnight on 2010-01-10. Again, the solution is you want an exclusive boundary at the top of the range:
request.date < '2019-01-10'
As a complete side note to the question, I'm a very sad the SQL BETWEEN operator is inclusive at both end of the range. This may make sense for numeric or string data, but for date values defining an exclusive upper bound for the BETWEEN operator would have made much more sense.

DATEDIFF SQL Query

I am at the final stage of my project and have the problem to find if a job is overdue. I link this to priority for example if a job has a priority of 1 it must be complete in 1 day, a priority of 4 then 4 days.
I have come up with a CASE however this doesn't seem to work any help would be appreciated.
SELECT `defect_Id`,`Overtasked`
WHERE
CASE DATEDIFF(DD,`date_Investigaton` - `CURRENT_DATE()`) >= `priority` AS Overtasked
THEN `Overtasked` == 'YES'
ELSE `Overtasked` == 'NO'
END
Solution
`SELECT defect_Id,
CASE WHEN DATEDIFF(date_Investigated, CURDATE()) >= priority
THEN 'YES'
ELSE 'NO'
END AS Overtasked
FROM defect_report
WHERE defect_Id = '82'`
Appreciate the guidance you guys give!
You are completely mixing up SQL dialects and even there are syntax errors.
Assuming you are talking about MS SQL Server let's try this:
SELECT defect_Id,
CASE WHEN DATEDIFF(DD, date_Investigaton, getdate()) >= priority
THEN 'YES'
ELSE 'NO'
END AS Overtasked
FROM <YourTable>
WHERE <YourWhereIfAny>
If date_Investigation is a DATE column, the subtraction date_Investigation - CURRENT_DATE() produces the number of days you need.
Otherwise (if it is a DATETIME, for example) both operands are converted to float and the result is something you are totally not expecting. For such situations use the DATEDIFF() function. It interprets its arguments as DATE (ignores the time part) and returns the integer number of days between the two dates.
Your query should be like:
SELECT
`defect_Id`,
IF (DATEDIFF(`date_Investigaton`, CURRENT_DATE()) >= `priority`, 'YES', 'NO')
AS `Overtasked`
FROM [...your table name here...]
WHERE [...conditions...]
Replace the parts in square brackets ([...]) with the name of the table where to get the data from and some conditions to limit the number of returned rows (otherwise it will get the entire table which, most probably, is not what you want).
Btw, CURRENT_DATE() is also a function. If you write it in backquotes (``), MySQL will try to find a column with this name and it will fail.
Read the accepted answer for this question. It explains when to use back ticks, single quotes or double quotes in MySQL (and partially in PHP).

MySql calculation returning zero when no record

Good morning, banging my head against a wall with this & was hoping to get some advice. I have 3 tables joined to display sales data as below;
Select
a._CommMonth As Month,
Sum(a._CommDue) As Commission,
Sum(a.`Network Paid`) As Company,
Sum(a.Payable) As Adviser,
c.Fee As Charge,
Sum(a.Payable) - (c.Fee) As Total
From
pms_payments.dbo_payments a
Inner Join pms_payments.dbo_nscontacts b
On b._Firm_Name = a._Firm_Name
Left Join pms_payments.dbo_clawback c
On b.ContactID = c.ContactID And a._CommMonth = c.Month
Where
b.ContactID = 199
Group By
a._CommMonth
The Sum(a.Payable) - (c.Fee) As Total field is where I am having issues, if no record exists in c.fee table then nothing is returned such as 100 - [No record] = 100. If a record is present the value is deducted as expected such as 100 - 15 = 85.
Does that make sense?
Thanks
Have a look at using IFNULL
IFNULL(expr1,expr2)
If expr1 is not NULL, IFNULL() returns expr1; otherwise it returns
expr2. IFNULL() returns a numeric or string value, depending on the
context in which it is used.
Something like
Sum(a.Payable) - IFNULL(c.Fee,0)
If I understand your question correctly, instead of getting 100 - no record = 100, you are getting 100 - no record = [nothing].
Presuming this is correct, then I believe your problem stems from the fact that null is not the same as zero (and is not a valid number). You can use the IFNULL() function to replace a null value with zero and your subtraction should work.
Please let me know if I misunderstood the question.
Hi there & thanks to you both, the IFNULL function was exactly what I needed. Sorry I could not accept both answers, really appreciate the effort & time though.
Sum(a.Payable) - IFNULL (c.Fee,0) As Total
Regards
Gary

Inequality sign in SQL case statement seems to work backwards?

n00b questioner here. I'm trying to do a query that checks if the most recent activity is within the last 24 hours. I technically can get the result I want, but the inequality in my case statement has to be in the opposite direction as would make sense to me. Here's my query:
SELECT sqs.registration_id,
MAX(sqs.completed_at) AS 'most recent activity',
DATE_SUB(NOW(), INTERVAL 1 DAY) AS 'one day ago',
'recent activity?' = CASE
WHEN MAX(sqs.completed_at) <
DATE_SUB(NOW(), INTERVAL 1 DAY)
THEN 1
ELSE 0
END
FROM student_quiz_states sqs
WHERE sqs.score = 100
GROUP BY sqs.registration_id
Here's an example result:
XXXXX 2011-08-02 16:23:53 2011-12-05 00:06:05 0
This user did not have activity in the last 24 hours, so the last value returns 0, as I want it to.
However, that doesn't make any sense to me. Shouldn't the case statement return a 1, since the first datetime is much earlier than one day ago? It would make sense to me if my desired results were returned when my when_clause contained a > instead of a <.
Any explanations would be appreciated.
The problem is that your query contains 'recent activity?' = CASE ... END where it should have CASE ... END AS 'recent activity?'. The former is an equality-test rather than an expression with an alias. The reason for the seemingly "inverted" behavior is that, since the CASE expression is numeric (it evaluates to 0 or 1), MySQL performs a numeric equality-test, by converting 'recent activity?' to 0.0 (detailed rules here), such that 'recent activity?' = CASE ... END is true when the CASE expression gives 0 and false when it gives 1. Since MySQL represents true as 1 and false as 0, the end result is the opposite of what you were expecting.
(Note: An earlier version of this answer, while making the same basic point about equality-tests vs. aliases, and about false and true being 0 and 1, was vague/confused in other respects, since I didn't recognize that the DBMS was MySQL, and was not aware that some DBMSes allow single-quotes to be used when quoting aliases. So if some of the comments above and below seem a bit strange, it's because they're referring to that version. The current state of the answer is thanks in large part to those comments.)