What does "<>" mean in Oracle - sql

What does <> mean in SQL language: Sample code is as follows
SELECT ordid,
prodid,
qty
FROM item
WHERE prodid IN (SELECT prodid
FROM item
WHERE ordid = 605)
AND qty IN (SELECT qty
FROM item
WHERE ordid = 605)
AND ordid <> 605;

It means 'not equal to'. So you're filtering out records where ordid is 605. Overall you're looking for any records which have the same prodid and qty values as those assigned to ordid 605, but which are for a different order.

Does not equal. The opposite of =, equivalent to !=.
Also, for everyone's info, this can return a non-zero number of rows. I see the OP has reformatted his question so it's a bit clearer, but as far as I can tell, this finds records where product ID is among those found in order #605, as is quantity, but it's not actually order #605. If order #605 contains 1 apple, 2 bananas and 3 crayons, #604 should match if it contains 2 apples (but not 3 dogs). It just won't match order #605. (And if ordid is unique, then it would find exact duplicates.)

It just means "different of", some languages uses !=, others (like SQL) <>

not equals. See here for a list of conditions

I'm surprised nobody mentioned the null special case. I think the meaning of <> is more something like
has a value which is not equal to
In this case it filters out items which have ordid 605 and items which have a null ordid.
It may be obvious in this context that ordid is never null, but it is never hurts to remember that null is not <> from 605 (or from anything).

It means not equal to
Should I use != or <> for not equal in TSQL?
Have a look at the link. It has detailed explanation of what to use for what.

It (<>) is a function that is used to compare values in database table.
!= (Not equal to) functions the same as the <> (Not equal to) comparison operator.

It means not equal to, this is a good method to exclude certain elements from your query. For example lets say you have an orders tables and then you have OrderStatusID column within that table.
You also have a status table where
0 = OnHold,
1 = Processing,
2 = WaitingPayment,
3 = Shipped,
4 = Canceled.
You can run a query where
Select * From [Orders] where OrderStatusID <> 4
this should give you all the orders except those that have been canceled! :D

Related

Missing records if add "NOT IN"

I have a table of doctor names and states.
f_name | l_name | state
MICHAEL | CRANE |
HAL | CRANE | MD
THOMAS | ROMINA | DE
And so on.
What I want is to get all doctors that are NOT in MD. However, if I write this expression I'm missing those with NULL values for state.
SELECT *
FROM doctors
WHERE state NOT IN ('MD')
I don't understand the issue. I was able to fix it by adding
OR state IS NULL
Obviously it has something to due with NOT IN (or IN) not handling NULL. Can anyone explain this for me? Is there an alternative for what I was trying to do?
Thanks
Yes, there is an alternative - you would use the NVL() function (or COALESCE() if you want to stick to the ANSI standard):
SELECT * FROM doctors
WHERE NVL(state, '##') NOT IN ('MD')
However you don't really need to use NOT IN here - it's only necessary when you have multiple values, e.g.:
SELECT * FROM doctors
WHERE NVL(state, '##') NOT IN ('MD','PA')
With one value you can just use = (or in this case, != or <>):
SELECT * FROM doctors
WHERE NVL(state, '##') != 'MD'
In Oracle SQL, NULL can't be compared to other values (not even other NULLs). So WHERE NULL = NULL, for example, will return zero rows. You do NULL comparisons with IS NULL and IS NOT NULL.
As noted already, you don't know that Michael Crane's state isn't Maryland. It's NULL, which can be read as representing "don't know". It might be Maryland, or it might not be. NOT IN ('MD') only finds those values known not to be 'MD'.
If you have a filter WHERE x, you can use MINUS to find exactly those records where x is not true (where x is either false or unknown).
select *
from doctors
minus
select *
from doctors
where state in ('MD');
This has one big advantage over anything involving IS NULL or NVL: it's immediately obvious exactly which records you don't want to see. You don't have to worry about accidentally missing one case where NULL isn't covered in your condition, and you don't have to worry about records that happen to match whatever dummy value you use with NVL.
It's generally not good for performance on Oracle, accessing the table twice, but for one-off queries, depending on the table size, the time saved writing the query can be more than the added execution time.
Inside database, null are not physical string values("null"), it simply says no value. So, if you compare NULLs to anything, it will not be equal or not equal. Even, two NULL's are not equal. You can only check whetherr a value is NULL or not but you can't compare it to other values.

Writing a query to include certain values but exclude others when looking for a latest time period

I am trying to write a query that looks for a people that have a certain code with the latest period (year) but not if they have another code with that latest period(year). I'll be explicit just so my example makes sense.
I want people who have the code A1,A2,A3,A4,A5 but not AG,AP,AQ. There are people who have an A1 code for a period (like 2014) and an AG code for a the same period. I'd like to exclude them. Not everyone has a code so the field value could be NULL.
Is there a way to express this in a different way (i.e. less characters) than the way I did?
SELECT
people.firstName
FROM
people
WHERE EXISTS (
SELECT *
FROM codes
WHERE
codes.people_id = people.id
AND period = (SELECT MAX(period) FROM codes codes2 WHERE codes2.people_id = codes.people_id)
AND code LIKE 'A[1-5]'
)
AND NOT EXISTS (
SELECT *
FROM codes
WHERE
codes.people_id = people.id
AND period = (
SELECT MAX(period)
FROM codes codes2
WHERE codes2.people_id = codes.people_id
)
AND code LIKE 'A[GPQ]'
)
Schema is as follows:
People
id (PK)
firstName
Codes
people_id (FK) many to one relation with People table
code (e.g. "A1", "A2", "AG")
period (e.g. "2013", "2014")
There are so many ways you could do that, I'm not an SQL expert but I can't see your query being too bad, if you want to try and reduce the number of sub-queries you could consider using the GROUP BY clause along with a SUM Aggregate function in a HAVING clause.
I started updating your code as follows:
SELECT
people.firstName
FROM
people
LEFT JOIN codes AS a15 ON a15.people_id = people.id AND a15.code LIKE 'A[1-5]'
LEFT JOIN codes AS agpq ON agpq.people_id = people.id AND agpq.code LIKE 'A[GPQ]'
GROUP BY
people.firstName
HAVING
SUM(CASE WHEN a15.code IS NULL THEN 0 ELSE 1 END) > 0
AND SUM(CASE WHEN agpq.code IS NULL THEN 0 ELSE 1 END) = 0
This however doesn't take into account anything to do with period specific requirements described. You could add the period to the GROUP BY clause or add it to a WHERE or one of the JOIN constraints but I'm not quite sure from your description exactly what you're after (I don't believe this is through any fault of your own, I just can't personally align the code provided to the description).
I would also like to point out that the SUM functions above will not give an accurate count of the number of matching codes. This is because if both A[GPQ] and A[1_5] return at least one row, the number returned by each constraint will be multiplied by the number returned for the other, it can however be used to determine if there are "any" returned items as if the criteria is matched it will have a SUM(...) > 0
I'm sure a more experienced SQL Developer / DBA will be able to poke many holes in my proposed query but it might give them or someone else something to work from and hopefully gives you ideas for alternatives to using sub-queries.

Round up prices to end with 99p

My table name is products and i am trying to update products_price so all prices have 99p at the end. Can you help?
Also this request is a bit simpler (i'm new to SQL!) I want to update all records as follows
anything in categories where parent_id is >0 I need the script to update all records to zero.
Q1
So, you want all prices to be truncated and then add 0.99 currency units. The function to truncate a value to 0 decimal places varies between DBMS; I'm assuming it is called TRUNC, but it might be called FLOOR or something else in your DBMS:
UPDATE Products
SET Products_Price = TRUNC(Products_Price) + 0.99;
You don't need a WHERE clause here. I'm assuming there are no negative prices; if that's a possibility, then you need to be a little cleverer with your assignment (maybe a CASE expression; maybe you have a function SIGN, SIGN, SIGNUM available).
Note that I'm assuming that the p referenced is pence, as in 'pounds (Sterling) and pence'. If the price was between £0.00 and £0.99, the result will be £0.99; if the price was between £1.00 and £1.99, the result will be £1.99; etc. The TRUNC or FLOOR will remove any fractional part from the price, and the addition of 0.99 then means that the result is of the form £x.99 for (non-negative) integer values of x.
Q2
Making some assumptions about what you meant:
UPDATE Categories
SET Anything = 0
WHERE Anything > 0
AND Parent_ID > 0;
If you meant that you want to update the products table in some way, then you need to be a lot more precise in your question.
Q2 revisited
From a comment:
I want to update all parent_id values in my categories table to zero where parent_id > 0.
Presumably, there must be some parent_id values which are null or negative, so you need:
UPDATE Categories
SET Parent_ID = 0
WHERE Parent_ID > 0
If there are no nulls and no negatives, then you can run an even simpler update:
UPDATE Categories
SET Parent_ID = 0
It will set to zero those rows which already have a parent ID of zero as well as those that do not. This might hit the logs a bit harder than the more selective update (as in, there will be more changes to record in the logical log or equivalent for your DBMS), but unless there are vast numbers of records and most of them already have a zero parent ID and the DBMS does not recognize when a record does not change and writes log records for unchanged rows, then you're unlikely to notice the difference
Set price to have 99p at end:
update products_price set price = floor(price)+0.99;
Set parent_id to 0:
update categories set parent_id = 0 where parent_id > 0;

What does "WHERE id <> 0" clause mean in SQL?

Query: SELECT id, name, FROM users u WHERE **id <> 0** LIMIT 50 OFFSET 0
What does the clause id <> 0 mean here? Does it mean:
id is less than zero or id is greater than zero
<> means "not equal" (it can also be written as != with some DBMS)
It means not equal and apparently I have to submit at least 30 characters for my answer.
It means, "where ID is different from 0".
So, both greater than or less than 0.
it means that you are fetching all records with an id different than 0 (zero), I've sometimes used this just to check if some record is already saved (if the record has an ID it means is saved).
It means only include results who's field id has a value of greater or smaller than 0, basically records that have non-zero id's - but really this should not be possible, if it is then I'd recommend reconsidering your table designs.

SQL Output Question

Edited
I am running into an error and I know what is happening but I can't see what is causing it. Below is the sql code I am using. Basically I am getting the general results I want, however I am not accurately giving the query the correct 'where' clause.
If this is of any assistance. The count is coming out as this:
Total Tier
1 High
2 Low
There are 4 records in the Enrollment table. 3 are active, and 1 is not. Only 2 of the records should be displayed. 1 for High, and 1 for low. The second Low record that is in the total was flagged as 'inactive' on 12/30/2010 and reflagged again on 1/12/2011 so it should not be in the results. I changed the initial '<=' to '=' and the results stayed the same.
I need to exclude any record from Enrollments_Status_Change that where the "active_status" was changed to 0 before the date.
SELECT COUNT(dbo.Enrollments.Customer_ID) AS Total,
dbo.Phone_Tier.Tier
FROM dbo.Phone_Tier as p
JOIN dbo.Enrollments as eON p.Phone_Model = e.Phone_Model
WHERE (e.Customer_ID NOT IN
(Select Customer_ID
From dbo.Enrollment_Status_Change as Status
Where (Change_Date >'12/31/2010')))
GROUP BY dbo.Phone_Tier.Tier
Thanks for any assistance and I apologize for any confusion. This is my first time here and i'm trying to correct my etiquette on the fly.
If you don't want any of the fields from that table dbo.Enrollment_Status_Change, and you don't seem to use it in any way — why even include it in the JOINs? Just leave it out.
Plus: start using table aliases. This is very hard to read if you use the full table name in each JOIN condition and WHERE clause.
Your code should be:
SELECT
COUNT(e.Customer_ID) AS Total, p.Tier
FROM
dbo.Phone_Tier p
INNER JOIN
dbo.Enrollments e ON p.Phone_Model = e.Phone_Model
WHERE
e.Active_Status = 1
AND EXISTS (SELECT DISTINCT Customer_ID
FROM dbo.Enrollment_Status_Change AS Status
WHERE (Change_Date <= '12/31/2010'))
GROUP BY
p.Tier
Also: most likely, your EXISTS check is wrong — since you didn't post your table structures, I can only guess — but my guess would be:
AND EXISTS (SELECT * FROM dbo.Enrollment_Status_Change
WHERE Change_Date <= '12/31/2010' AND CustomerID = e.CustomerID)
Check for existence of any entries in dbo.Enrollment_Status_Change for the customer defined by e.CustomerID, with a Change_Date before that cut-off date. Right?
Assuming you want to:
exclude all customers whose latest enrollment_status_change record was since the start of 2011
but
include all customers whose latest enrollment_status_change record was earlier than the end of 2010 (why else would you have put that EXISTS clause in?)
Then this should do it:
SELECT COUNT(e.Customer_ID) AS Total,
p.Tier
FROM dbo.Phone_Tier p
JOIN dbo.Enrollments e ON p.Phone_Model = e.Phone_Model
WHERE dbo.Enrollments.Active_Status = 1
AND e.Customer_ID NOT IN (
SELECT Customer_ID
FROM dbo.Enrollment_Status_Change status
WHERE (Change_Date >= '2011-01-01')
)
GROUP BY p.Tier
Basically, the problem with your code is that joining a one-to-many table will always increase the row count. If you wanted to exclude all the records that had a matching row in the other table this would be fine -- you could just use a LEFT JOIN and then set a WHERE clause like Customer_ID IS NULL.
But because you want to exclude a subset of the enrollment_status_change table, you must use a subquery.
Your intention is not clear from the example given, but if you wanted to exclude anyone who's enrollment_status_change as before 2011, but include those who's status change was since 2011, you'd just swap the date comparator for <.
Is this any help?