TSQL Where Statement OR + AND - tsql

I have a very basic SELECT statement that is causing me some grief.
I have a primary table of tools that I am selecting data from. In that table, I only want tools where the status is not Decommissioned.
From there, I am checking the tool name against my LIKE clause to see if it's a close match. This is done for my AJAX typeahead.
Lastly, it's joining a table called akas which contains tool names that can also be used in reference to the main tool. These are basically other aliases the tools go by.
The issue I am facing is that it is still including records with the Decommissioned status. I am pretty sure its the WHERE clause.. Any thoughts?
SELECT t.toolName,
t.tool AS toolID,
t.toolType,
t.toolStatus,
e1.PreferredName AS ownerFirst,
e1.LastName AS ownerLast,
e1.NTID AS ownerNTID
FROM dbo.ti_tools AS t
LEFT OUTER JOIN
dbo.ti_toolAKAs AS a
ON t.tool = a.tool
LEFT OUTER JOIN dbo.EmployeeTable AS e1
ON t.toolOwner = e1.QID
WHERE (t.toolName LIKE '%' + #tool + '%') OR (a.aka LIKE '%' + #tool + '%')
AND t.toolStatus <> 'Decommissioned'
ORDER BY t.toolName ASC
FOR XML PATH ('tools'), TYPE, ELEMENTS, ROOT ('root');

Order of operations
AND has greater precedence than OR.
Change your WHERE clause to the following, using parentheses around the two OR conditions to separate them logically from the commission check:
WHERE ((t.toolName LIKE '%' + #tool + '%') OR (a.aka LIKE '%' + #tool + '%'))
AND t.toolStatus <> 'Decommissioned'
Your original WHERE clause was being evaluated identically to this:
WHERE (t.toolName LIKE '%' + #tool + '%') OR
((a.aka LIKE '%' + #tool + '%') AND t.toolStatus <> 'Decommissioned')

Add round brackets:
SELECT t.toolName,
t.tool AS toolID,
t.toolType,
t.toolStatus,
e1.PreferredName AS ownerFirst,
e1.LastName AS ownerLast,
e1.NTID AS ownerNTID
FROM dbo.ti_tools AS t
LEFT OUTER JOIN dbo.ti_toolAKAs AS a
ON t.tool = a.tool
LEFT OUTER JOIN dbo.EmployeeTable AS e1
ON t.toolOwner = e1.QID
WHERE ((t.toolName LIKE '%' + #tool + '%') OR (a.aka LIKE '%' + #tool + '%'))
AND t.toolStatus <> 'Decommissioned'
ORDER BY t.toolName ASC
FOR XML PATH ('tools'), TYPE, ELEMENTS, ROOT ('root');
The case is very simple:
cond1 OR cond2 AND cond3
<=>
cond1 OR (cond2 AND cond3)
And you get records that satisfy only cond1. What you really want is:
(cond1 OR cond2) AND cond3

Related

Postgresql - How to make NOT LIKE + SELECT statement, comparing two columns between tables

Hit a bit of a brickwall here, I haven't found anything that seems to work.
SELECT *
FROM glsltransaction gls
INNER JOIN glhistory h ON gls.sltrxid = h.schedxrefid
INNER JOIN apvendor ap ON ap.vendorid = gls.acctid
INNER JOIN glchartofaccounts coa USING (acctdeptid)
WHERE h.description <> gls.description
AND h.description not like || ap.name || '%'
AND gls.description <> ''
This line here AND h.description not like || ap.name || '%' is what i'm having issues with.
I get the following error when trying to run that statement above:
'Error occurred in running query from editor : ERROR: operator does not exist: || text Hint: No operator matches the given name and argument type. You might need to add an explicit type cast. Position: 563'
I'm effectively wanting it to function like a.column not like b.column%
Any help will be greatly appreciated, thanks!

Postgres SQL - different results from LIKE query using OR vs ||

I have a table with an integer column. It has 12 records numbered 1000 to 1012. Remember, these are ints.
This query returns, as expected, 12 results:
select count(*) from proposals where qd_number::text like '%10%'
as does this:
SELECT COUNT(*) FROM "proposals" WHERE (lower(first_name) LIKE '%10%' OR qd_number::text LIKE '%10%' )
but this query returns 2 records:
SELECT COUNT(*) FROM "proposals" WHERE (lower(first_name) || ' ' || qd_number::text LIKE '%10%' )
which implies using || in concatenated where expressions is not equivalent to using OR. Is that correct or am I missing something else here?
You probably have nulls in first_name. For these records (lower(first_name) || ' ' || qd_number::text results in null, so you don't find the numbers any longer.
using || in concatenated where expressions is not equivalent to using ORIs that correct or am I missing something else here?
That is correct.
|| is the string concatenation operator in SQL, not the OR operator.

Postgresql SELECT if string contains

So I have a in my Postgresql:
TAG_TABLE
==========================
id tag_name
--------------------------
1 aaa
2 bbb
3 ccc
To simplify my problem,
What I want to do is SELECT 'id' from TAG_TABLE when a string "aaaaaaaa" contains the 'tag_name'.
So ideally, it should only return "1", which is the ID for tag name 'aaa'
This is what I am doing so far:
SELECT id FROM TAG_TABLE WHERE 'aaaaaaaaaaa' LIKE '%tag_name%'
But obviously, this does not work, since the postgres thinks that '%tag_name%' means a pattern containing the substring 'tag_name' instead of the actual data value under that column.
How do I pass the tag_name to the pattern??
You should use tag_name outside of quotes; then it's interpreted as a field of the record. Concatenate using '||' with the literal percent signs:
SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' LIKE '%' || tag_name || '%';
And remember that LIKE is case-sensitive. If you need a case-insensitive comparison, you could do this:
SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' LIKE '%' || LOWER(tag_name) || '%';
A proper way to search for a substring is to use position function instead of like expression, which requires escaping %, _ and an escape character (\ by default):
SELECT id FROM TAG_TABLE WHERE position(tag_name in 'aaaaaaaaaaa')>0;
I personally prefer the simpler syntax of the ~ operator.
SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' ~ tag_name;
Worth reading through Difference between LIKE and ~ in Postgres to understand the difference.
`
In addition to the solution with 'aaaaaaaa' LIKE '%' || tag_name || '%' there
are position (reversed order of args) and strpos.
SELECT id FROM TAG_TABLE WHERE strpos('aaaaaaaa', tag_name) > 0
Besides what is more efficient (LIKE looks less efficient, but an index might change things), there is a very minor issue with LIKE: tag_name of course should not contain % and especially _ (single char wildcard), to give no false positives.
SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' LIKE '%' || "tag_name" || '%';
tag_name should be in quotation otherwise it will give error as tag_name doest not exist

T-SQL if exists

I am summer intern new to T-SQL and I have to run an sql select statement on various databases. What I would like to do is use 'if exists' to keep an error from occuring because some of the databases on the list to have this statement executed on no longer exist. However, I cannot figure out how to apply it to my statement. Any help would be greatly appreciated. Below is the statment me and another intern wrote:
select distinct mg.MatterName, mg.ClientNumber, mg.MatterNumber,grp.groupName as SecurityGroup
from (select distinct mat.matterName, mat.clientNumber, mat.matterNumber, usr.GroupID
from <db_name>.dbo.matter mat
inner join <db_name>.dbo.usrAccount usr
on usr.NTlogin=mat.matterCreateBy) as mg
inner join <db_name>.dbo.usrGroup grp
on mg.groupID=grp.groupID
order by matterName
the < db_name> is where the passed in parameter that is the name of the database, would go.
You could use sp_MSforeachdb to enumerate all of the databases on the instance.
This would be similar to:
exec sp_MSforeachdb 'select distinct mg.MatterName, mg.ClientNumber, mg.MatterNumber,grp.groupName as SecurityGroup from (select distinct mat.matterName, mat.clientNumber, mat.matterNumber, usr.GroupID from ?.dbo.matter mat inner join ?.dbo.usrAccount usr on usr.NTlogin=mat.matterCreateBy) as mg inner join ?.dbo.usrGroup grp on mg.groupID=grp.groupID order by matterName'
Alternatively, you could use dynamic sql to manufacture a script:
select 'use ' + name + ';' + char(13) + 'select distinct mg.MatterName, mg.ClientNumber, mg.MatterNumber,grp.groupName as SecurityGroup' +CHAR(13) + 'from (select distinct mat.matterName, mat.clientNumber, mat.matterNumber, usr.GroupID' + char(13) + 'from dbo.matter mat' + char(13) + 'inner join dbo.usrAccount usr on usr.NTlogin=mat.matterCreateBy) as mg' + char(13) + 'inner join dbo.usrGroup grp on mg.groupID=grp.groupID' + CHAR(13) + 'order by matterName;'
from master.sys.databases where database_id>4
If you redirect your output to "Results to Text" in SSMS then run the script, you will see a script written that you can then put into a query editor to execute.
I got it to work. I think this is a bit hackey but what I did was catch the exception thrown and just change a label on the page to reflect that the database doesnt exist.
DataAccess dal = new DataAccess();
dal.SelectedConnectionString = "WebServer08";
String exNetName = Request.QueryString["name"];
if (exNetName != null && !exNetName.Equals(""))
{
try
{
gvMatters.DataSource = dal.GetMatters(exNetName);
gvMatters.DataBind();
}
catch (Exception ex)
{
noDB.Text = "This database doesn't exist.";
gvMatters.Visible = false;
}
}
And i just left the SQL statement the way it was rather than try to screw around with it

Like and And Or ISNull using Linq to Entity Entity Framework4? How do you do that?

I have a screen in my project " Enquiry" where I user can perform 2 kinds of search.I cannot figure out how to do a "like" or "And or is null" in Linq to entity.
Simple Search ( Search in all fields using "Like" operator)
Advanced Advanced Search (Use "And" Operator)
So lets take these 3 tables and make up a noddy example.
Customer Table (CustomerID,Name,Surname)
Address(AddressID,Street,City)
CustomerOrder (OrderID,OrderName)
Basic search :
this is how I would do it in Sql
SELECT TOP (100) C.Name,C.Surname,CA.Street,CA.City,CO.OrderName
FROM Customer C
LEFT JOIN CustomerAddress CA ON C.CustomerID=CA.CustomerID
LEFT JOIN CustomerOrders CO ON C.CustomerID=CA.CustomerID
WHERE (C.CustomerID LIKE '%' + #SearchText + '%'
OR C.Surname LIKE '%' + #SearchText + '%'
OR C.Name LIKE '%' + #SearchText + '%'
OR CA.Street LIKE '%' + #SearchText + '%'
OR CA.City LIKE '%' + #SearchText + '%'
OR CO.OrderName LIKE '%' + #SearchText + '%') )
Advanced Search
This my sql where clause
WHERE (C.CustomerID =#CustomerID or #CustomerID ISNULL
AND C.Surname =#Surname or #Surname ISNULL
AND C.Name=#Name or #Name ISNULL
AND CA.Street =#Street or #Street ISNULL
AND CA.City =#City or #City ISNULL
AND CO.OrderName =#OrderName or #OrderName ISNULL)
AND ((ModifiedDate BETWEEN ISNULL(convert(varchar,#FromDate,101),'01/01/1901')
AND ISNULL(convert(varchar,#ToDate,101),'12/31/9999'))
How do you do Likes or and or is null in entity framework?
thanks a lot!
For LIKE, you can use Contains, StartsWith, or EndsWith. For IS NULL, use == null.
Example:
var list = from p in Products
where (p.Description.Contains("v") && p.Description.StartsWith("C"))
|| p.MFRCode == "TOYOTA"
|| p.Universal == null
select p;
will cause EF to generate this SQL:
SELECT
[Extent1].[MFRCode] AS [MFRCode],
[Extent1].[MFRProductID] AS [MFRProductID],
[Extent1].[Universal] AS [Universal],
[Extent1].[Description] AS [Description]
FROM [dbo].[Products] AS [Extent1]
WHERE (([Extent1].[Description] LIKE N'%v%') AND ([Extent1].[Description] LIKE N'C%')) OR (N'TOYOTA' = [Extent1].[MFRCode]) OR ([Extent1].[Universal] IS NULL)
and produce these results:
Edit
I used LINQPad to generate these results. It's a great tool, free to use (there's an option to purchase an Intellisense feature), and definitely worth a look if you'd like to experiment with different LINQ queries and see the SQL that EF is generating (it's good for general LINQ experimentation and quickly trying out simple code as well).
int? customerID = null;
string surname = "abc";
var q = from c in oc.Customers
where (customerID == null || c.CustomerID == customerID)
&& (surname == null || c.Surname == surname)
select c;