Reputation: 10748
Example:
CREATE TABLE [UserClass]
(
[UserId] [varchar](50) NOT NULL,
[ClassId] [varchar](50) NOT NULL,
[Status] [tinyint] NOT NULL
)
INSERT INTO [UserClass]
VALUES ('UserA', 'ClassX', 5), ('UserA', 'ClassY', 5), ('UserA', 'ClassZ', 6),
('UserB', 'ClassX', 5), ('UserB', 'ClassY', 6), ('UserB', 'ClassZ', 5),
('UserC', 'ClassY', 6), ('UserC', 'ClassZ', 6)
I want a query to count the number of classes where a given user is the only member of a given status.
I have created the following query, which seems to work for this purpose:
DECLARE @UserId VARCHAR(50) = 'UserA'
DECLARE @Status TINYINT = 5
SELECT
COUNT(1)
FROM
[UserClass] UC
WHERE
UC.[UserId] = @UserId
AND UC.[Status] = @Status
AND (SELECT COUNT(1)
FROM [UserClass] UC2
WHERE UC2.[ClassId] = UC.[ClassId]
AND UC2.[Status] = @Status) = 1
This query uses a sub-select in the where clause.
Is there a better way to write this query in order to avoid the sub-select?
Fiddle: http://sqlfiddle.com/#!6/5c871/1
Upvotes: 1
Views: 65
Reputation: 43636
You can do this:
WITH DS AS
(
SELECT *
,COUNT(*) OVER (PARTITION BY [ClassId], [Status]) AS [Count]
FROM [dbo].[UserClass]
)
SELECT *
FROM DS
WHERE [Count] = 1
AND [UserID] = @UserId
AND @Status = @Status;
Upvotes: 1
Reputation: 10701
I do not think that there is a way to do it without subselect, however, I would use the NOT EXISTS
for it:
SELECT UserClass.*
FROM UserClass
WHERE UserClass.[Status] = @Status and
UserClass.UserId = @UserId and
NOT EXISTS
(
SELECT 1
FROM [UserClass] UC
WHERE UC.[Status] = UserClass.[Status] and
UC.[ClassId] = UserClass.[ClassId] and
UC.[UserId] != UserClass.[UserId]
)
Upvotes: 0
Reputation: 70523
Here is the typical way you would do this:
SELECT ClassID
FROM UserClass
GROUP BY ClassID
HAVING COUNT(*) = 1
Upvotes: -1