SQL, comparing two values and returning values that don't match - sql

i'm running a sql statement that reads values from two different databases and returns records that do not match.
The two fields i'm trying to compare are:
NAME_TYPE which is a number eg. 1 or 2
PartyType which is varchar eg. Person/Organisation
How might I compare this effectively?
Most of them have been easy to compare like NAM.NAME <> cl.ClientName.
But I'm finding this a bit more difficult, new user to sql so any help would be great, thanks.

This may work;
WHERE NOT ((NAM.NAME_TYPE = 1 and cl.PartyType = 'Person') OR (NAM.NAME_TYPE =2 and cl.PartyType = 'Organisation'))

Related

SQL statement only returns a single row, where it should return multiple

I have database that contains data points from various sensors. These data points are taken twice a minute.
I am using the following SQL query to attempt to get two separate data points at two different times.
SELECT *
FROM TableName
WHERE TagName = 'TagName'
AND ("DateTime" = 'X' OR "DateTime" = 'Y')
I see no reason why this should not return 2 data points, one for the first date, and one for the second, but for some reason the query only returns the row for Y.
I feel like I am missing something extremely obvious.
For a bit more context, this query is used in conjuction with a python script to grab data between two dates using a specific resolution.
Any ideas?
EDIT: I believe it has something to do with the structure of the database and how it operates in terms of giving entries a time value.
It needs more investigation on my part so im going to flag this question for deletion, thanks all for you help
Not sure if that is a mistype in your question, but if not, it is probably the " after the AND part of the statement:
AND ("DateTime" = 'X' OR "DateTime" = 'Y')
It should be AND (DateTime = 'X' OR DateTime = 'Y'). Notice no quotes.
http://sqlfiddle.com/#!2/ed00ba/3

String ending in range of numbers

I have a column with data of the following structure:
aaa5644988
aaa4898494
aaa5642185
aaa5482312
aaa4648848
I have a range that can be anything, like 100-30000 or example. I want to have all values that end in numbers between that range.
I tried
like '%[100-30000]'
but this doesn't work apparently.
I have seen a lot of similar questions but none of the solved my problem
edit I'm using SQL server 2008
Example:
Value
aaa45645695
aaa28568720
aaa65818450
8789212
6566700
For the range 600-1200, I want to retrieve row 1,2,5 because they end with the range.
In SQL, like normally only support % and _ these two operators. That's why like '%[100-30000]' doesn't work.
Depend on your use case, there could be two solutions for this problem:
If you only need to do this query two or three times(didn't care how long it takes), or the dataset is not very big. You can select all the data from this column, and then do the filtering in another programming language.
Take ruby for example, you can do:
column_data = #connection.execute("select * from your_column_name")
result = column_data.map{|x| x.gsub(/^.*[^\d]/, '').to_i }.select{|x| x > 100 && x < 30000}
If you need to do this query regularly, I'd suggest you add a new column to this data table with only the numbers in the current column, so as to get a much better performance in querying speed.
SELECT *
FROM your_table
WHERE number_column BETWEEN 100 AND 30000

SQL BETWEEN return empty rows even if value exist

what am I doing wrong with my sql query? It always return an empty rows even if there is a value exist.
Here is my query:
SELECT *
FROM users
WHERE user_theme_id IN ( 9735, 9325, 4128 )
AND ( user_date_created BETWEEN '2013-06-04' AND '2013-06-10' );
I tried to cut my original query one by one, I got a result. Here is the first one:
SELECT * FROM users WHERE user_theme_id IN (9735, 9325, 4128 );
I got 3 rows for this result. See attached snapshot:
Now, the next query that I run is this:
SELECT *
FROM users
WHERE user_date_created BETWEEN '2013-06-04' AND '2013-06-10';
I do get 3 results on this. See attached snapshot:
By the way, this sql that uses BETWEEN should suppose return 4 rows but it only return 3. It doesn't return the data which has the created date of 2013-06-10 08:27:43
What am I doing wrong with my original query Why does it always return an empty rows?
If you are getting results by separately running different where clauses doesn't guarantee that AND 2 where clauses will return an answer.
There has to be intersection of rows to get result while AND.
You should validate your data and see if overlapping exists.
I have able to make it work by not using the SQL BETWEEN operators but instead COMPARISON OPERATORS like: >= || <=
I have read it from W3schools.com, the SQL between can produce different results in different databases.
This is the content:
Notice that the BETWEEN operator can produce different result in different databases!
In some databases, BETWEEN selects fields that are between and excluding the test values.
In other databases, BETWEEN selects fields that are between and including the test values.
And in other databases, BETWEEN selects fields between the test values, including the first test value and excluding the last test value.
Therefore: Check how your database treats the BETWEEN operator!
That is what happened in the issue that I am facing. The first field was being treated as part of the test values and the 2nd field was being excluded. Using the comparison operators give accurate result.

Splitting text in SQL Server stored procedure

I'm working with a database, where one of the fields I extract is something like:
1-117 3-134 3-133
Each of these number sets represents a different set of data in another table. Taking 1-117 as an example, 1 = equipment ID, and 117 = equipment settings.
I have another table from which I need to extract data based on the previous field. It has two columns that split equipment ID and settings. Essentially, I need a way to go from the queried column 1-117 and run a query to extract data from another table where 1 and 117 are two separate corresponding columns.
So, is there anyway to split this number to run this query?
Also, how would I split those three numbers (1-117 3-134 3-133) into three different query sets?
The tricky part here is that this column can have any number of sets here (such as 1-117 3-133 or 1-117 3-134 3-133 2-131).
I'm creating these queries in a stored procedure as part of a larger document to display the extracted data.
Thanks for any help.
Since you didn't provide the DB vendor, here's two posts that answer this question for SQL Server and Oracle respectively...
T-SQL: Opposite to string concatenation - how to split string into multiple records
Splitting comma separated string in a PL/SQL stored proc
And if you're using some other DBMS, go search for "splitting text ". I can almost guarantee you're not the first one to ask, and there's answers for every DBMS flavor out there.
As you said the format is constant though, you could also do something simpler using a SUBSTRING function.
EDIT in response to OP comment...
Since you're using SQL Server, and you said that these values are always in a consistent format, you can do something as simple as using SUBSTRING to get each part of the value and assign them to T-SQL variables, where you can then use them to do whatever you want, like using them in the predicate of a query.
Assuming that what you said is true about the format always being #-### (exactly 1 digit, a dash, and 3 digits) this is fairly easy.
WITH EquipmentSettings AS (
SELECT
S.*,
Convert(int, Substring(S.AwfulMultivalue, V.Value * 6 - 5, 1) EquipmentID,
Convert(int, Substring(S.AwfulMultivalue, V.Value * 6 - 3, 3) Settings
FROM
SourceTable S
INNER JOIN master.dbo.spt_values V
ON V.Value BETWEEN 1 AND Len(S.AwfulMultivalue) / 6
WHERE
V.type = 'P'
)
SELECT
E.Whatever,
D.Whatever
FROM
EquipmentSettings E
INNER JOIN DestinationTable D
ON E.EquipmentID = D.EquipmentID
AND E.Settings = D.Settings
In SQL Server 2005+ this query will support 1365 values in the string.
If the length of the digits can vary, then it's a little harder. Let me know.
Incase if the sets does not increase by more than 4 then you can use Parsename to retrieve the result
Declare #Num varchar(20)
Set #Num='1-117 3-134 3-133'
select parsename(replace (#Num,' ','.'),3)
Result :- 1-117
Now again use parsename on the same resultset
Select parsename(replace(parsename(replace (#Num,' ','.'),3),'-','.'),1)
Result :- 117
If the there are more than 4 values then use split functions

SQL Server 2008 UPDATE Statement WHERE clause precedence

I wrote the following query:
UPDATE king_in
SET IN_PNSN_ALL_TP_CNTRCT_CD = IN_PNSN_ALL_TP_CNTRCT_CD + '3'
WHERE COALESCE(IN_PNSN_ALL_TP_CNTRCT_TX, '') <> ''
AND CHARINDEX('3', IN_PNSN_ALL_TP_CNTRCT_CD) = 0
It checks to see if a field has a value in it and if it does it puts a 3 in a corresponding field if there isn't a 3 already in it. When I ran it, I got a string or binary data will be truncated error. The field is a VARCHAR(3) and there are rows in the table that already have 3 characters in them but the rows that I was actually doing the updating on via the WHERE filter had a MAX LEN of 2 so I was completely baffled as to why SQL Server was throwing me the truncation error. So I changed my UPDATE statement to:
UPDATE king_in
SET IN_PNSN_ALL_TP_CNTRCT_CD = k.IN_PNSN_ALL_TP_CNTRCT_CD + '3'
FROM king_in k
INNER JOIN
(
SELECT ki.row_key,
in_sqnc_nb
FROM king_in ki
INNER JOIN King_Ma km
ON ki.Row_Key = km.Row_Key
INNER JOIN King_Recs kr
ON km.doc_loc_nb = kr.ACK_ID
WHERE CHARINDEX('3', IN_PNSN_ALL_TP_CNTRCT_CD) = 0
AND COALESCE(IN_PNSN_ALL_TP_CNTRCT_TX, '') <> ''
) a
ON k.Row_Key = a.Row_Key
AND k.in_sqnc_nb = a.insr_sqnc_nb
and it works fine without error.
So it appears based on this that when doing an UPDATE statement without a FROM clause that SQL Server internally goes through and runs the SET statement before it filters the records based on the WHERE clause. Thats why I was getting the truncation error, because even though the records I wanted to update were less than 3 characters, there were rows in the table that had 3 characters in that field and when it couldn't add a '3' to the end of one of those rows, it threw the error.
So after all of that, I've got a handful of questions.
1) Why? Is there a specific DBMS reason that SQL Server wouldn't filter the result set before applying the SET statement?
2) Is this just a known thing about SQL that I never learned along the way?
3) Is there a setting in SQL Server to change this behavior?
Thanks in advance.
1 - Likely because your criteria are not SARGable - that is, they can't use an index. If the query optimizer determines it's faster to do a table scan, it'll go ahead and run on all the rows. This is especially likely when you filter on a function applied to the field like you do here.
2 - Yes. The optimizer will do what it thinks it best. You can get around this somewhat by using parentheses to force an evaluation order of your WHERE clause but in your example I don't think it would help since it forces a table scan regardless.
3 - No, you need to alter your data or your logic to allow indexes to be used. If you really really need to filter on existence of a certain character in a field, it probably should be it's own column and/or you should normalize that particular bit of data better.
A workaround for your particular instance would be to add a WHERE LEN(IN_PNSN_ALL_TP_CNTRCT_CD) < 3 as well.