SQL If statement for specific user - sql

So I have 2 users, one called admin, the other one called admin2.
I have wrote a SQL query in which I want to increase an achievement of a specific account, in my case only for admin, but inspite of that, the same achievement for user admin2 is also affected. What am I doing wrong?
DECLARE #Achievement1 INT
SELECT #Achievement1 = Achievement1
FROM [dbo].[Achievement]
WHERE [dbo].[Achievement].UserID = (SELECT [AccountID]
FROM [dbo].[Account]
WHERE [Username] = 'Admin')
IF (#Achievement1 < 100)
UPDATE [dbo].[Achievement]
SET [Achievement1] += 2
ELSE
UPDATE [dbo].[Achievement]
SET [Achievement1] += 0

Your code is updating all rows in Achievement when the condition is met. It is not just updating the matching row.
Your logic is rather convoluted. I think you can just do this:
UPDATE a
SET Achievement1 += 2
FROM dbo.Achievement a
WHERE a.Achievement1 < 100 AND
a.UserId = (SELECT ac.AccountId
FROM dbo.Account ac
WHERE ac.UserName = 'admin'
);
Note: Having UserId in one table match AccountId in another is quite confusing. Are you sure the comparison should not be either user ids or account ids?

No need for all of this, you can just update with join like this:
UPDATE a1
SET a1.[Achievement1] = CASE WHEN a1.Achievement1 < 100 THEN a1.[Achievement1] + 2
ELSE a1.[Achievement1] END
FROM [dbo].[Achievement] AS a1
INNER JOIN [dbo].[Account] AS a2 ON a1.UserID = a2.[AccountID]
WHERE a2.UserName = 'admin';

Related

Update Column in table using Select, Inner Join and Case When

I have a table called: Claim, where I've already moved data from another table called Damage. However, today I needed to add a column in Claim called ClaimStatusID. And to give values to ClaimStatusID I need to to it based on another column called DamageApprovedStatusID, which exists in yet another table called DamageErrand. Damage and DamageErrand has relation through a crosstable called DamageErrandCrossDamage. In that crosstable DamageErrandID and DamageID exists. Here, I've commented more information:
-- Claim has column ID which has the same ID as the table Damage
-- DamageErrand has DamageApprovedStatus ID which need to be inserted
-- to ClaimStatusID, where the ID's need to be correct.
-- Table Damage and Table DamageErrand has a cross table:
-- DamageErrandCrossDamage, where both of their ID's are stored
-- Claim.ID should therefore be the same as DamageErrandCrossDamage.DamageID
-- Since Claim.ID has the same ID as Damage.ID
-- IF DamageApprovedStatus = -1, SET ClaimStatusID = 0
-- IF DamageApprovedStatus = 0, SET ClaimStatusID = 4
-- IF DamageApprovedStatus = 1, SET ClaimStatusID = 2
And here's a SQL query I created for selecting and using Case When to give the correct statuses:
SELECT Claim.ID as claimid, DamageErrandID as damageerrandeid,
CASE --
WHEN DamageErrand.DamageApprovedStatusID = -1 THEN 0
WHEN DamageErrand.DamageApprovedStatusID = 0 THEN 4
WHEN DamageErrand.DamageApprovedStatusID = 1 THEN 2
ELSE '-'
END AS DamageApprovedStatusID,
DamageApprovedStatusID
FROM
DamageErrand
INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID =
DamageErrandCrossDamage.DamageErrandID
INNER JOIN Claim ON DamageErrandCrossDamage.DamageID = Claim.ID
WHERE Claim.ID = DamageErrandCrossDamage.DamageID
I do believe this is correct, with the ID's matching and everything. But how can I actually update the table Claim with this? I know insert won't work since I have columns that does not allow null in Claim table. I tried doing something similar to:
--UPDATE Claim
--SET ClaimStatusID =
--(SELECT DamageApprovedStatusID FROM
--DamageErrand
--INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID =
-- DamageErrandCrossDamage.DamageErrandID
--INNER JOIN Claim ON DamageErrandCrossDamage.DamageID = Claim.ID
--WHERE Claim.ID = DamageErrandCrossDamage.DamageID)
But obviously this won't work either. Really thankful for any help!
Btw: I'm using SQL-server for this.
I believe something like this should work:
UPDATE Claim
SET ClaimStatusID = alias.DamageApprovedStatusID
FROM (
SELECT DamageErrandCrossDamage.DamageID,
CASE
WHEN DamageErrand.DamageApprovedStatusID = -1 THEN 0
WHEN DamageErrand.DamageApprovedStatusID = 0 THEN 4
WHEN DamageErrand.DamageApprovedStatusID = 1 THEN 2
ELSE '-'
END AS DamageApprovedStatusID
FROM DamageErrand
INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID = DamageErrandCrossDamage.DamageErrandID
) alias
WHERE Claim.ID = alias.DamageID
I guess it could be rewritten like this too:
UPDATE Claim
SET ClaimStatusID = CASE
WHEN DamageErrand.DamageApprovedStatusID = -1 THEN 0
WHEN DamageErrand.DamageApprovedStatusID = 0 THEN 4
WHEN DamageErrand.DamageApprovedStatusID = 1 THEN 2
ELSE '-'
END
FROM DamageErrand
INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID = DamageErrandCrossDamage.DamageErrandID
INNER JOIN Claim ON DamageErrandCrossDamage.DamageID = Claim.ID

Update multiple rows with data from another table

I have to update 700 rows on a table. Is it possible to do it with only one query?
2 examples:
UPDATE PERSON p SET p.admin = (select usr.iqid from USER usr where usr.userid = 'J072') where upper(person.myid) = '18349';
UPDATE PERSON p SET p.admin = (select usr.iqid from USER usr where usr.userid = 'PU96') where upper(person.myid) = '36895';
I would write this as:
UPDATE PERSON p
SET p.admin = (SELECT u.iqid
FROM USER u
WHERE (u.userid = 'J072' AND p.myid = '18349') OR
(u.userid = 'PU96' AND p.myid = '36895')
)
WHERE p.myid IN ('18349', '36895');
Notes that upper() is not needed for numbers. It would generally impede the use of indexes.
Option 1.
update person p
set p.admin =
(select usr.iqid
from user usr
where usr.userid = decode(upper(person.myid), '36895', 'PU96', '18349', 'J072'))
where upper(person.myid) = any ('36895', '18349');
Option 2.
Use merge statement to avoid correlated scalar subquery.
Option 3.
Update (select ... from person join user) set ... if person has foreign key references user.
Google "key preserned view".

SQL select query in update

I am trying to fix this query:
I have an update query.
UPDATE controll_SZHEAD14
LEFT JOIN [outgoing] ON controll_SZHEAD14.sa_code = [outgoing].Account
SET [outgoing].Account = controll_SZHEAD14.sa_code, [outgoing].Buyer = controll_SZHEAD14.sa_buyername, [outgoing].startdate = controll_SZHEAD14.sa_date, [outgoing].Finance = controll_SZHEAD14.sa_tedat, [outgoing].maxdate = controll_SZHEAD14.sa_esdat, [outgoing].[25alap] = controll_SZHEAD14.sa_summary
WHERE (((controll_SZHEAD14.sa_code)>"BA14/01997"));
So if I run this query above, than refresh my data, but only from BA14/01997 till now. So in this example this will refresh 66 row. (66 row affected)
I have this simple select SQL:
SELECT TOP 1 Account FROM [outgoing] ORDER BY Account DESC;
If I run this above I got the last account, in this example:BA14/01997
So I would like to take this two query "update+select" together.
UPDATE controll_SZHEAD14
LEFT JOIN [outgoing] ON controll_SZHEAD14.sa_code = [outgoing].Account
SET [outgoing].Account = controll_SZHEAD14.sa_code, [outgoing].Buyer = controll_SZHEAD14.sa_buyername, [outgoing].startdate = controll_SZHEAD14.sa_date, [outgoing].Finance = controll_SZHEAD14.sa_tedat, [outgoing].maxdate = controll_SZHEAD14.sa_esdat, [outgoing].[25alap] = controll_SZHEAD14.sa_summary
WHERE (((controll_SZHEAD14.sa_code)>"SELECT TOP 1 Account FROM [outgoing] GROUP BY Account DESC;"));
The above query does not work properly. When I run, I got 0 row affected, but I expect the same as the first update query.
Any idea how to fix this?
Enclose the SELECT statement in ( ) brackets
UPDATE controll_SZHEAD14
LEFT JOIN [outgoing]
ON controll_SZHEAD14.sa_code = [outgoing].Account
SET [outgoing].Account = controll_SZHEAD14.sa_code,
[outgoing].Buyer = controll_SZHEAD14.sa_buyername,
[outgoing].startdate = controll_SZHEAD14.sa_date,
[outgoing].Finance = controll_SZHEAD14.sa_tedat,
[outgoing].maxdate = controll_SZHEAD14.sa_esdat,
[outgoing].[25alap] = controll_SZHEAD14.sa_summary
WHERE controll_SZHEAD14.sa_code > (
SELECT TOP 1 Account
FROM [outgoing]
ORDER BY Account DESC
);

sql query updates all rows and not only where clause

I am having trouble executing this query:
update public.fortune_companies
set industry_id = (select id
from public.industries
where name = 'Agriculture, Forestry and Fishing')
from Temp_Sic_Fortune_Companies as temp
left join public.fortune_companies as fc on fc.account_name = temp.account_name
where temp.sic between '0' and '499';
I think this is supposed to set the industry_id for only ones that have a sic number of 0-499 but it actually sets every record to the same id. No matter if the sic number is between 0-499 or not.
Why is this.
DECLARE #id INT;
SELECT #id = id
FROM public.industries
WHERE name = 'Agriculture, Forestry and Fishing';
UPDATE fc
SET industry_id = #id
FROM public.fortune_companies AS fc
WHERE EXISTS
(
SELECT 1
FROM dbo.Temp_Sic_Fortune_Companies
WHERE account_name = fc.account_name
AND sic BETWEEN '0' and '499'
);
Of course, if temp.sic = '3000', it will be part of the set. This is one of the dangers of using the wrong data type (or the wrong operator). You can fix that by saying:
AND sic BETWEEN '0' and '499'
AND LEN(sic) <= 3
Or by saying:
AND CASE WHEN ISNUMERIC(sic) = 1 THEN
CONVERT(INT, sic) ELSE -1 END BETWEEN 0 AND 499
(This avoids errors if - since you've let them - someone enters a non-numeric value into the column.)
Or by using the right data type in the first place.
Change the left join to inner join

Need to create a report for contacts that have missed workflow activities

We had an issue where our workflows have not been creating activities.
I now need to report which accounts have not had their workflows invoked.
I've tried advanced find and then moved to sql.
My question is can someone provide a simple starter query to pull which 'entity' has NOT had a specific activity associated with it?
Please let me know if the question is not clear enough or more info, is needed.
Below is a solution using SQL where I step through my thought process, and below that is a solution that gets started with the C# API (edit: just realized this is for a report, so that part can be disregarded). I've commented in most places, so I hope my methods are fairly straightforward.
SQL
1.
--get all the entities that aren't activities and aren't intersect entities (N:N tables)
--Put in your own where conditions to further filter this list,
--which is still probably far too expansive
SELECT
A.name EntityName
FROM MetadataSchema.Entity A
WHERE
A.IsActivity = 0
AND A.IsIntersect = 0
2.
--CROSS JOIN the non-activity entities with the activity entities
--to get a list of all possible entity/activity pairings
SELECT DISTINCT
A.name EntityName
, B.Name ActivityName
FROM MetadataSchema.Entity A
CROSS JOIN MetadataSchema.Entity B
WHERE
A.IsActivity = 0
AND A.IsIntersect = 0
AND B.IsActivity = 1
3.
--LEFT JOIN the partial cartesian join above against the Activity table,
--making a note of which entities actually have activity records.
--This will provide a complete list of which entity/activity pairings
--exist and don't exist
SELECT
A.name EntityName
, B.Name ActivityName
--if there is a matching activity, the unique key,
--ActivityTypeCode (int), will be positive.
--So, if there is a positive sum for an entity/activity
--pairing, you know there is a valid pair; otherwise
--no pair
, CAST(CASE WHEN sum(coalesce(C.ActivityTypeCode, 0)) > 0
THEN 1
ELSE 0
END AS BIT) EntityOwnsActivity
FROM MetadataSchema.Entity A
CROSS JOIN MetadataSchema.Entity B
LEFT JOIN dbo.ActivityPointer C ON
--ObjectTypeCode is a unique identifier for Entities;
--RegardingObjectTypeCode is the code for the entity type
--associated with a particular activity
A.ObjectTypeCode = C.RegardingObjectTypeCode
--ActivityTypeCode is the code for the particular activity
AND B.ObjectTypeCode = C.ActivityTypeCode
WHERE
A.IsActivity = 0
AND A.IsIntersect = 0
AND B.IsActivity = 1
GROUP BY
A.name
, B.Name
4.
--Putting it all together, using the above master table,
--filter out the entities/activities you're interested in
--(in this case, all entities that aren't associated with
--any emails)
SELECT
EntityName
FROM
(
SELECT
A.name EntityName
, B.Name ActivityName
, CAST(CASE WHEN sum(coalesce(C.ActivityTypeCode, 0)) > 0
THEN 1
ELSE 0
END AS BIT) EntityOwnsActivity
FROM MetadataSchema.Entity A
CROSS JOIN MetadataSchema.Entity B
LEFT JOIN dbo.ActivityPointer C ON
A.ObjectTypeCode = C.RegardingObjectTypeCode
AND B.ObjectTypeCode = C.ActivityTypeCode
WHERE
A.IsActivity = 0
AND A.IsIntersect = 0
AND B.IsActivity = 1
GROUP BY
A.name
, B.Name
) EntityActivities
WHERE ActivityName = 'Email'
AND EntityOwnsActivity = 0
ORDER BY
EntityName
C#.NET API
using (OrganizationServiceProxy _serviceProxy =
new OrganizationServiceProxy(
new Uri(".../XRMServices/2011/Organization.svc"), null, null, null))
{
_serviceProxy.EnableProxyTypes();
RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest()
{
EntityFilters = EntityFilters.Entity,
RetrieveAsIfPublished = true
};
// Retrieve the MetaData.
EntityMetadata[] entities =
((RetrieveAllEntitiesResponse)_serviceProxy.Execute(request)).EntityMetadata;
var ents = from e1 in entities.Where(x => x.IsActivity != true)
.Where(x => x.IsIntersect != true)
from e2 in entities.Where(x => x.IsActivity == true)
select new
{
entityName = e1.SchemaName
,
activityName = e2.SchemaName
};
//at this point, because of the limited nature of the Linq provider for left joins
//and sums, probably the best approach is to do a fetch query on each entity/activity
//combo, do some sort of sum and find out which combos have matches
// in the activity pointer table
//API = very inefficient; maybe improved in next CRM release? Let's hope so!
}