how to update a column with multiple values except particular values - sql

tUser table is having values
UserID UserName Email isActive
---------------------------------------------
1 abc abc#gmail.com 1
2 abc abc#gmail.com 1
3 abc abc#gmail.com 1
4 abc abc#gmail.com 1
22 cd cd#gmail.com 1
23 cd cd#gmail.com 1
24 ef ef#gmail.com 1
25 ef ef#gmail.com 1
The values are duplicate of UserName abc.
I have a query to update isActive column of UserName 'abc'.
UPDATE dbo.tUser
SET isActive = 0
FROM Duplicates d,dbo.tUser
WHERE d.UserId =dbo.tUser.UserId
and d.RN>1
But it is updating the first column of UserName 'abc'. I need to keep a particular userID '4' as 1 and other values to update with 0. How can i do it?
If i need to include 4,23 and 25. How can i do it?
i tried with
;WITH Duplicates AS
(
SELECT [UserId],[UserName],[Email],
RN = ROW_NUMBER()OVER(PARTITION BY[UserName],[Email] ORDER BY [UserName],[Email])
from dbo.tUser
)
UPDATE U
SET isActive = (case when U.UserId IN (4,23,25) THEN 1 ELSE 0 END)
FROM Duplicates d
JOIN dbo.tUser U
ON d.UserId =U.UserId
and d.RN>1
But it is not working

If I understand the question correctly, you can just use a CASE expression:
UPDATE u
SET isActive = (CASE WHEN u.UserId = 4 THEN 1 ELSE 0 END)
FROM Duplicates d JOIN
dbo.tUser u
ON d.UserId = u.UserId
WHERE d.RN > 1;
Note: Learn to use proper explicit JOIN syntax. Simple rule: Never use commas in the FROM clause.

First of all what is d.RN? What is the structure of the Duplicates table? Is it possible that Duplicates.UserId may contain an Id that is similar to tUser.UserId yet refer to a totally different record?
The following script will work for you (however it's not fully tested as I don't have an IDE and SQLFiddler seem to be down:
UPDATE u
SET u.IsActive = 0
FROM dbo.tUser u
LEFT JOIN (SELECT UserId, RANK() OVER (Partition [UserName], [Email] ORDER BY [UserName], [Email]) AS RNK) d
ON d.UserId = tUser.UserId
WHERE d.RNK > 1

Related

Return Duplicate emails along with User Ids that are different

I'm running into an issue with a duplicate query and I hope you guys can help.
Essentially what I want to do is find and list of the duplicate emails associated with different userids
My query is:
select UserId, acitveid, email, userstatusid
from (select u.UserId, u.acitveid, cd.email, u.userstatusid,
count(*)over (partition by cd.email) as cnt
from ContactDetails cd
join UserContactDetails ucd on ucd.ContactDetailsId = cd.ContactDetailsId
join dbo.[User] u on u.UserId = ucd.UserId ) ua
where cnt >1
The issue I have with the above query is that it is returning the same userids for some of the results so it looks like:
Userid AcitveId email UserStatusid
123 1 abc#123.com 1
123 1 abc#123.com 1
135 1 efg#123.com 1
142 1 efg#123.com 1
The results Im looking for are simply:
Userid AcitveId email UserStatusid
135 1 efg#123.com 1
142 1 efg#123.com 1
WITH base AS (
SELECT DISTINCT u.UserId
,u.acitveid
,cd.email
,u.userstatusid
,
FROM ContactDetails cd
JOIN UserContactDetails ucd ON ucd.ContactDetailsId = cd.ContactDetailsId
JOIN dbo.[User] u ON u.UserId = ucd.UserId
)
,duplicate_emails AS (
SELECT email
,count(userId) AS cnt
FROM base
GROUP BY 1
HAVING count(userId) > 1
)
SELECT b.*
FROM base b
JOIN duplicate_emails de ON b.email = de.email
A self join across Email = email and id <> id would work fine here. That said, your request and lack of sample data means that we are largely guessing based off the query and sample output you have provided. The below should get you pretty close and, if you update your OP, I am sure we can get you exactly what you're after.
SELECT ActiveUser.UserID Active_UserID,
ActiveUser.ActiveID Active_ActiveID,
ContactDetails.email AS Email,
DuplicateUser.UserID AS Dup_UserID,
DuplicateUser.ActiveID As Dup_ActiveID
FROM ContactDetails INNER JOIN
ContactDetails AS Duplicate ON ContactDetails.email = Duplicate.email AND ContactDetails.UserID <> Duplicate.UserID INNER JOIN
UserContactDetails AS ActiveUserContactDetails ON ActiveUserContactDetails.ContactDetailsID = ContactDetails.ContactDetailsID INNER JOIN
dbo.[User] AS ActiveUser ON ActiveUser.UserID = ActiveUserContactDetails.UserID INNER JOIN
UserContactDetails AS DuplicateUserContactDetails ON DuplicateUserContactDetails.ContactDetailsID = Duplicate.ContactDetailsID INNER JOIN
dbo.[User] AS DuplicateUser ON DuplicateUser.UserID = UserContactDetails.UserID

SQL Code to get results when there are no records in a table

There are 4 tables (user, user options, option type 1, and option type 2). The user table is not directly involved here but mentioned for completeness. Here are the table columns for each of the involved tables.
User Options:
UserID,
Option1ID,
Option2ID,
Option1:
Option1ID,
Option1Description
Option2:
Option2ID,
Option2Description
All the values for Option1 can be combined with all the values for Option2 hence if there a 'x' number of Option1 values and 'y' number of Option2 values then the resultant number of option combinations is 'x' * 'y'. I want to write a query such that it will always result in 'x' * 'y' rows for a given UserID even if there is no record for a particular combination of Option1ID and Option2ID for that user in the UserOptions table. Additionally there should be a column that indicates if the particular combination of Option1 and Option2 exists in the UserOptions table.
Option1
Option1ID Option1Description
----------------------------------
1 1_Description1
2 1_Description2
Options2
Option2ID Option2Description
----------------------------------
1 2_Description1
2 2_Description2
UserOptions
UserID Option1ID Option2ID
---------------------------------
1 1 2
1 2 2
Result
UserID Option1ID Option2ID Exists
----------------------------------------------
1 1 1 0
1 1 2 1
1 2 1 0
1 2 2 1
Given the above what would the SQL query be? In addition note that UserID = 2 does not exist in the UsersOptions table. In this case the query should still return 4 records where the UserID column will always be 2, the OptionID columns will be the same, and the Exists column will always be 0.
You can cross join the users table with the two options tables to generate all possible combinations, then search for a match in bridge table useroptions with a left join:
select u.userid, o1.option1id, o2.option2id,
case when uo.userid is null then 0 else 1 end as uo_exists
from users u
cross join option1 o1
cross join option2 o2
left join useroptions uo
on uo.userid = u.id
and uo.option1id = o1.option1id
and uo.option2id = o1.option2id
You could also use exists instead of a left join:
select u.userid, o1.option1id, o2.option2id,
case when exists (
select 1
from useroptions uo
where uo.userid = u.id and uo.option1id = o1.option1id and uo.option2id = o1.option2iduo.userid
) then 1 else 0 end as uo_exists
from users u
cross join option1 o1
cross join option2 o2

Get Incremental index for specific rows

I want to get the incremental index when note exists for the row. I am trying to achieve the same with ROW_Number() but it seems there is a problem with the method being used to generate it.
SELECT * RowNo,
(SELECT CASE
WHEN LEN(Value) > 0 THEN ROW_NUMBER()
OVER (
ORDER BY ID)
ELSE ''
END
FROM Dictionary
WHERE ID = ABC.ID) Note
FROM ABCD AS ABC WITH(NOLOCK)
INNER JOIN XYZ AS XYZ WITH(NOLOCK)
ON ABC.Id = XYZ.ID
WHERE ABC.Id = 10
output expected:
ID Name Note
1 A 1
2 B
3 C 2
4 D
5 E
6 F 3
The subquery isn't needed here, and you want to use the partition by argument to separate values having len(value)>0 from those having no value:
SELECT
ID,
Name,
CASE WHEN LEN(Value)>0 THEN ROW_NUMBER() OVER (
PARTITION BY CASE WHEN LEN(Value)>0 THEN 1 ELSE 0 END
ORDER BY ID) ELSE '' END as Note
FROM ABCD AS ABC WITH(NOLOCK)
INNER JOIN XYZ AS XYZ WITH(NOLOCK)
ON ABC.Id = XYZ.ID
Where ABC.Id = 10
I think maybe you need to change the approach to make the Dictionary query the "main" query. It's hard to say without knowing exactly what your tables look like. Which Table does the "Id" in your expected output come from?
Try like this:
WITH cte AS (
SELECT ID, ROW_NUMBER() OVER (ORDER BY ID) AS Note
FROM Dictionary WHERE ID=10
AND LEN(Value)>0
)
SELECT ABC.ID, [Name], cte.Note
FROM ABCD AS ABC WITH(NOLOCK)
INNER JOIN XYZ AS XYZ WITH(NOLOCK) ON ABC.Id = XYZ.ID
LEFT OUTER JOIN cte ON ABC.Id=cte.ID

SQL query to check if user assigned with a specific value and does not a different value assigned to the same user?

We can have users with multiple valueIDs. In SQL Server I am trying to pull all users that have valueID of 3 but do not have valueID of 1 and 2. So Table A would have a user column and a valueID column.
How do I write a SQL query to do this?
Also, any good resources to get my SQL query skills up to par?
Much appreciated.
Try:
SELECT user
FROM A outer
WHERE valueID = 3
AND NOT EXISTS
(
SELECT 1
FROM A inner
WHERE
(
valueID = 1
OR valueID = 2
)
AND inner.user = outer.user
)
Here's one more.... (all users with valueid = 3 and nothing else)
SELECT [USER]
FROM A
GROUP BY [USER]
HAVING MAX(CASE WHEN valueid = 3 THEN 0 when valueid IN (1,2) THEN 1 END) = 0;
This query will return all users that have values (3 and 1) or (3 and 2) or just 3
select user
from mytable t1
where valueId = 3
and (select count(distinct valueId)
from mytable t2 where t2.user = t1.user
and valueId IN (1,2)) < 2
A simple way to get what you asked if you meant users with a value of 3 except those which also have values of 1 and 2
Select s.UserID From SomeTable s
Where s.UserID NOT In
(select s1s.UserID From SomeTable s1s
inner join SomeTable s2s On s1s.UserID = s2s.UserID
Where s1s.ValueId = 1 And s2s.ValueId = 2)
Or
Select s.UserID From SomeTable s
Left Join
(select s1s.UserID From SomeTable s1s
inner join SomeTable s2s On s1s.UserID = s2s.UserID
Where s1s.ValueId = 1 And s2s.ValueId = 2) both
Where both.userID is null
I'm not really sure what your table structure is, but it's likely the below query should work depending on column names...
SELECT user, valueID
FROM users
WHERE valueID = 3

SQL Data Rows as Columns

I am wanting to return columns representing various users for a CSV file for part of our database.
The base tables look something like this:
ProviderId ProviderName
1 Test
2 FooBar
UserId UserName
1 Mike
2 Bob
3 John
ProviderId UserId
1 1
2 2
1 3
I want the results to look like this:
ProviderName UserName1 UserName2 ...
Test Mike John
FooBar Bob
So far, I tried using pivot for this, but it only supports Ints (and thus only the Ids):
SELECT ProviderId, [1],[2],[3],[4] FROM (
SELECT p.ProviderId, u.UserId, ROW_NUMBER() OVER(PARTITION BY p.ProviderId ORDER BY p.ProviderId ASC, u.UserId ASC) as Row
FROM Provider p
left join ProviderUser pu on p.ProviderId=pu.ProviderId
left join [User] u on pu.UserId = u.UserId
) as MyTable
PIVOT
(
SUM(UserId) FOR Row IN ([1],[2],[3],[4])
) as PivotTable
ProviderId 1 2 3 4
1 2 15 18 22
2 17 23 NULL NULL
However, I need to be able to take the usernames (and other text details) out of user child rows and append them as columns per their provider parent.
Any suggestions for making this work?
Thanks
Ok, if you want to get a dynamic number of columns, then you are gonna have to use dynamic sql. For that, please take a look at this link first. Then, you can try this:
DECLARE #Users NVARCHAR(MAX), #Query NVARCHAR(MAX)
SET #Users = ''
SELECT #Users = #Users + '[UserName' + CAST(UserId AS VARCHAR) +'],'
FROM Users
ORDER BY UserId
SET #Users = LEFT(#Users,LEN(#Users)-1)
SET #Query = '
SELECT ProviderName, '+#Users+'
FROM ( SELECT B.ProviderName, C.UserName, ''UserName''+CAST(A.UserId AS VARCHAR) UserAlias
FROM ProviderUsers A
JOIN Provider B
ON A.ProviderId = B.ProviderId
JOIN Users C
ON A.UserId = C.UserId) T
PIVOT(MIN(UserName) FOR UserAlias IN ('+#Users+')) AS PT'
EXEC sp_executesql #Query