SQL Server : using SELECT in NOT IN WHERE Clause - sql-server

I've been using this query statement ever since. I wonder why this does not work on SQL Server 2008 R2.
SELECT
UserName
FROM
Users
WHERE
UserName NOT IN (SELECT UserName FROM UserTableT2)
The codes does not return any data. Goal is select all UserName in Users table which do not belong to UserTableT2.
EDIT:
Here's the actual query
Update using #Tim Schelmter's query:
Update :
Update:
Thank you!

I would use NOT EXISTS:
SELECT u.UserName
FROM Users u
WHERE NOT EXISTS
(
SELECT 1 FROM UserTableT2 ut2
WHERE u.UserName = ut2.UserName
)
Why? Because it works also if there are NULL values in UserTableT2.UserName.
Worth reading:
Instead of NOT IN, use a correlated NOT EXISTS for this query pattern.
Always. Other methods may rival it in terms of performance, when all
other variables are the same, but all of the other methods introduce
either performance problems or other challenges.
With your updated columns and tables:
SELECT u.usr_id
FROM ousr u
WHERE NOT EXISTS
(
SELECT 1 FROM ApprovalStageApprovers asa
WHERE u.usr_id = asa.ApprovalUser
)

Related

Assistance needed on Optimizing a view in SQL Server 2012

I am running SQL Server 2012 and have constructed a query to minus results one primary from another. I have done this a few ways one being:
SELECT
campaignContact_id,
nlLogID,
emailAddress
FROM
sm_rel_campaign_contact rcc
WHERE
rcc.campaignContact_id NOT IN (SELECT campaignContact_id
FROM SM_BOUNCES)
AND rcc.campaigncontact_id NOT IN (SELECT campaignContact_id
FROM SM_DEFERRALS )
AND rcc.campaignContact_id NOT IN (SELECT campaignContact_id
FROM SM_FAILS)
AND rcc.campaignContact_id NOT IN (SELECT campaignContact_id
FROM SM_SENDS )
Another being :
ALTER VIEW SM_QUEUE
AS
(
SELECT
campaignContact_id,
nlLogID,
emailAddress
FROM
sm_rel_campaign_contact rcc
WHERE
NOT EXISTS (SELECT * FROM SM_BOUNCES smb
WHERE rcc.campaignContact_id = smb.campaignContact_id)
AND NOT EXISTS (SELECT * FROM SM_DEFERRALS smd
WHERE rcc.campaignContact_id = smd.campaignContact_id)
AND NOT EXISTS (SELECT * FROM SM_FAILS smf
WHERE rcc.campaignContact_id = smf.campaignContact_id)
AND NOT EXISTS (SELECT * FROM SM_SENDS sms
WHERE rcc.campaignContact_id = sms.campaignContact_ID)
)
The issue is when I run this guy after I create the view (either way):
SELECT count(*)
FROM SM_QUEUE
WHERE nlLogID = 81505
it's running incredibly slow! I know you can index views but I wanted to see if anyone had a better suggestion? LEFT OUTER JOIN's maybe?
Appreciate any feedback in advance.
You won't be able to index this view - sub queries or outer joins make this unindexable.
Probably you are missing some useful indexes on the base tables though.
A possible different approach that may perform better is
WITH Excludes
AS (SELECT campaignContact_id
FROM SM_BOUNCES
UNION ALL
SELECT campaignContact_id
FROM SM_DEFERRALS
UNION ALL
SELECT campaignContact_id
FROM SM_FAILS
UNION ALL
SELECT campaignContact_id
FROM SM_SENDS)
SELECT campaignContact_id,
nlLogID,
emailAddress
FROM sm_rel_campaign_contact rcc
WHERE NOT EXISTS (SELECT *
FROM Excludes e
WHERE e.campaignContact_id = rcc.campaignContact_id)
If that doesn't help edit your question and include the CREATE TABLE statements including indexes and details of sizes of the tables involved.
'not in' cannot typically be optimzed (you end up with full table scans) but not exists can be optimized by the query analyzer. See if you can change the not in to a not exist in the first query.
cant really try it since sql fiddle is down and i have no sql server till monday (maybe you need a few more parentheses):
WITH cte AS (
SELECT campaignContact_id FROM sm_rel_campaign_contact rcc
except
SELECT campaignContact_id FROM SM_BOUNCES
except
SELECT campaignContact_id FROM SM_DEFERRALS
except
SELECT campaignContact_id FROM SM_FAILS
except
SELECT campaignContact_id FROM SM_SENDS)
SELECT *
from cte
join sm_rel_campaign_contact rcc on rcc.campaignContact_id = cte.campaignContact_id
I would expect the second version (with the WHERE NOT EXISTS()) to run quite a bit faster than the one with the WHERE NOT IN () construction. However, this requires that you have an index on the campaignContact_id field in each of the referenced tables (SM_BOUNCES, SM_DEFERRALS,SM_FAILS & SM_SENDS). Additionally, since you say these are big tables, do you have an index on the nlLogID field to start with? It might well be that your query spends more time scanning the sm_rel_campaign_contact table than figuring out if it has relevant data in the other tables; especially since you say both versions in the question run 'about the same'.
TIP: try running the query with the 'Show Execution Plan' and interpret what's going on there, or simply take a screenshot and attach it to your question above and see if we can get any insights from it.

How would I write this query with DBIX::Class?

I've seen a few other questions on Stackoverflow that discuss sub-selects, but they usually relate to the use of multiple tables. In most cases, a proper join could serve the same purpose.
However my query below refers to a single table. How would I write this using DBIX::Class?
select ID, username, email, role
from Employees
where (ID in
(select max(ID)
from Employees
where username = 'jsmith'
))
order by ID DESC
Thanks!
--
Edit 1: SQL code fix
The Cookbook has almost the exact same query as example.
Your SQL query doesn't make sense to me because the subquery returns a single id, so WHERE id = () would make more sense.
What are you trying to accomplish with it?

Duplicate Query in Microsoft Access or SQL Server

I have over 1,000 entries with duplicate values in an Access database. I want to create a column called Duplicate and set it to true if a record is NOT THE FIRST ONE with a particular value. This means, if the record is the first one with the value "Red Chair", the Duplicate field is set to false, but all subsequent records with value "Red Chair" will have the Duplicate field set to true.
How do I perform this query in Access?
This database will be upsized to an SQL Server database, so an option for me is to 'ignore' the duplicate records while retrieving the records in my SQL query. If this option is viable, I'd like to know how to do this in SQL as alternative. Thanks.
You will have to use subqueries. Try this
UPDATE Tabelle1 SET Tabelle1.b = 'Duplicate'
WHERE
((Tabelle1.[ID] In
(SELECT Tabelle1.[ID] FROM Tabelle1 WHERE
((Tabelle1.[a] In
(SELECT [a] FROM [Tabelle1] As Tmp GROUP BY [a] HAVING Count(*)>1 )
)
AND
(Tabelle1.[ID] Not In
(SELECT min([id]) FROM [Tabelle1] as grpid GROUP BY [a] HAVING Count(*)>1)
));
)));
I'm no expert on the Access dialect, but this adaptation of RJIGO's answer or something similar may also work and be more efficient:
UPDATE Tabelle1 SET
b = 'Duplicate'
WHERE
Tabelle1.[ID] > (
SELECT min([id])
FROM [Tabelle1] as T2
WHERE T2.[a] = Tabelle1.[a]
);
I hope this sql help u:
SELECT table.field, Count(table.field) AS test, IIf([test]>1,"TRUE","FALSE") AS check
FROM table
GROUP BY table.field, IIf([test]>1,"TRUE","FALSE");

SQL Server query one table based on conditions in second table

Can anyone help a newbie to SQL out please with this situation.
Given a membership database where there can be more than one member per membership account, is it possible to return all records from the membership table where no member (in the membername table) is over a specified age.
The tables look like this:
membership.id
membership.membershipnumber
membername.id
membername.membershipnumber
membername.name
membername.age
Many thanks
There are probably faster methods but this is a straightforward way of doing it.
Select membershipnumber
From membership
Where membershipnumber
Not In (
Select membershipnumber
From membername
Where age > #pAge
)
Select distinct m.membershipnumber
from membership s
inner join (select membershipnumber from membername where age > 18) aux on aux.membershipnumber = m.membershipnumber
You can replace 18 by a #variable.

SQL Subquery in LINQ for Entity Framework 4.0

I'm new to LINQ and EF, but I've been able to stumble through for the majority of the queries I have, but this one has me completely confused. No matter what I try, it comes up in SQL Profiler as a big mess :-).
I have two tables: Users and UsersProjects. The goal of this query is to list all the users who are working on projects with the specified user. Here is the query as I have it written in SQL. It's a subquery, but I don't know of a way to simplify it further, but I'm open to suggestions there as well.
SELECT DISTINCT Users.FirstName, Users.LastName
FROM Users INNER JOIN UsersProjects ON Users.ID=UsersProjects.UserID
WHERE UsersProjects.ProjectID IN
(SELECT ProjectID FROM UsersProjects WHERE UserID=#UserID)
Anybody able to help?? It seems like a fairly simple subquery in SQL, but in LINQ, I'm baffled.
Thanks,
Jorin
Something like this I guess:
from u in Users
from projectId in UsersProjects.Where(up => up.UserId == #userId).Select(p => p.ProjectId)
where u.UsersProjects.Any(up => projectId == up.ProjectId)
select u
or (it's your sql query in linq)
(from u in Users
join up in UsersProjects on #userId equals up.UserId
where u.UsersProjects.Any(up2 => up2.ProjectId == up.ProjectId)
select u).Distinct()

Resources