counting total active contacts for the account - salesforce

I have created a checkbox on contacts to represent it's status (active__c ) and another custom field for account object, which represent total number of active contacts (activeContact__c).
Below code is working fine but when I am making the total active contacts to zero for any account, it still come as 1.
Could you please explain what I am doing wrong here? Thanks.
trigger CountActiveContacts on Contact (after insert , after update) {
switch on Trigger.operationType {
when AFTER_INSERT, AFTER_UPDATE {
List<Account> accountList = new List<Account>();
Set<Id> accIds = new Set<Id>();
for(Contact c : Trigger.new){
accIds.add(c.AccountId);
}
AggregateResult[] groupedResult = [select accountid accID, count(id) totalCountOfActiveContacts from contact where active__c = true and AccountId =: accIds group by accountid ];
for(AggregateResult result: groupedResult){
accountList.add(new Account(id= (id)result.get('accID'), activeContact__c= (Integer) (result.get('totalCountOfActiveContacts'))));
}
update accountList;
}
}
}

When last contact got unticked your query starts to return 0 rows
select accountid accID, count(id) totalCountOfActiveContacts
from contact
where active__c = true and AccountId =: accIds
group by accountid
so there's nothing to loop over anymore.
Try making the Accounts as a Map and initialise the counter to zero. And you won't need the Set even
Map<Id, Account> accs = new Map<Id, Account>();
for(Contact c : trigger.new){
accs.put(c.AccountId, new Account(Id = c.AccountId, ActiveContact__c = 0));
}
AggregateResult[] groupedResult = [select accountid accID, count(id) totalCountOfActiveContacts from contact where active__c = true and AccountId =: accs.keyset() group by accountid ];
for(AggregateResult result: groupedResult){
accs.get((Id) result.get('accID')).ActiveContact__c = (Integer) result.get('totalCountOfActiveContacts');
}

Related

I want to generate serial Number automatically by adding plus 1 number in asp.net web api

How to take dataset and get max serial number from database generate number automatically by adding plus 1 number
var SerialNo = Convert.ToInt64(row[0]) + 1;
is this example is correct
My API
[HttpGet]
[Route("api/boq/getserialno/{id}")]
public BOQ GetBoqSerialNo(long id)
{
var result = new BOQ();
var dsBoq = SqlHelper.ExecuteDataset(AppDatabaseConnection, CommandType.StoredProcedure, 0, "GetSerialNo", new SqlParameter("#FinancialYearId", id));
if (dsBoq.Tables[0].Rows.Count > 0)
{
DataRow row = dsBoq.Tables[0].Rows[0];
var SerialNo = Convert.ToInt64(row[0]) + 1;
result = new BOQ
{
SerialNumber = Convert.ToInt64(row[0])
};
}
return result;
}
Stored procedure:
ALTER PROCEDURE [dbo].[GetSerialNo]
#FinancialYearId BIGINT
AS
BEGIN
SELECT MAX(SerialNumber) AS SerialNumber
FROM BillOfQuotation
WHERE FinancialYearId = #FinancialYearId
END
You may update your query by this:
string SQLString = "
UPDATE s SET s.SerialNumber= t.rno from BillOfQuotation as s
inner join (
select ROW_NUMBER() over (order by (select 1000)) as rno, * from
BillOfQuotation where FinancialYearId=#FinancialYearId ) as t
on s.col1=t.col1 and s.FinancialYearId=t.FinancialYearId
where s.FinancialYearId=#FinancialYearId " ----- here apply join as per the unique values in your table
Here we are generating unique row_number for each row and update it respectively as Serial No. If you have some column or id maintained for ordering then you may use that column instead of select 1000.

Check if record exists with Dapper ORM

What is the simplest way to check if record exists using the Dapper ORM?
Do I really need to define POCO objects for a query where I only want to check if a record exists?
int id = ...
var exists = conn.ExecuteScalar<bool>("select count(1) from Table where Id=#id", new {id});
should work...
I think this may have a tad less overhead as there's no function call or data type conversions:
int id = ...
var exists = connection.Query<object>(
"SELECT 1 WHERE EXISTS (SELECT 1 FROM MyTable WHERE ID = #id)", new { id })
.Any();
const string sql = "SELECT CAST(CASE WHEN EXISTS (SELECT 1 FROM MyTable WHERE Id = #Id) THEN 1 ELSE 0 END as BIT)";
bool exists = db.ExecuteScalar<bool>(sql, new { Id = 123 });
You can have your query to return a bool:
[Test]
public void TestExists()
{
var sql = #"with data as
(
select 1 as 'Id'
)
select CASE WHEN EXISTS (SELECT Id FROM data WHERE Id = 1)
THEN 1
ELSE 0
END AS result
from data ";
var result = _connection.Query<bool>(sql).FirstOrDefault();
Assert.That(result, Is.True);
}
conn.QuerySingleOrDefault<bool>("select top 1 1 from table where id=#id", new { id});
Another option that will run with duplicate records, i.e. not querying the id of the table
bool exists = connection.ExecuteScalar<int>(
"select count(1) from Table where notanId=#value", new { value = val})
> 0;
If you need to do this sort of query against a non-unique field you can use HAVING to handle counts greater than 1.
SELECT 1
FROM Table
WHERE Col=#val
HAVING COUNT(1) > 0
imho SELECT TOP(1) is better than SELECT COUNT(1)
bool exists = connection.Query<ValueTuple<long>>(
"SELECT top(1) Id FROM MYTABLE WHERE MYTABLE.Id=#Id",
new {Id}).Any());
The ValueTuple<long> is value type . Query<object> map to reference type and causes boxing .

Can I apply join on four tables or anything similar in Entity Framework?

I have four tables
Users
{
PK: UserId
...
}
Products
{
PK: ProductId
FK: UserId
...
}
ProductTags
{
PK: ProductTagId
FK: ProductId
...
}
LikedProducts
{
PK: Id
UserId
ProductId
...
}
Here is my query.
int userId = 1; //It will be different for different user.
var tblProductList = (from t in repo.ProductTags
join p in repo.Products on t.ProductId equals p.ProductId
join u in repo.LikedProducts on p.UserId equals u.UserId
join l in repo.LikedProducts on new { p.ProductId, userId } equals new { l.ProductId, l.UserId }
where productIdList.Contains(p.ProductId)
select p
).ToList();
I am getting The type of once reference in join clause is incorrect error.
I am getting list of ProductId let's say productListIds from azure search. My question is, Is it possible to get some column(Not all data) from each table using single query either by Join or using Entity Framework.
I googled It but didn't find any solution in which we could apply Join more than 3 tables.
Thanks in advance.
I am still unsure as to what you are trying to extract. Here is a corrected query though as you were using LikedProducts twice which is not necessary.
This would get a list of products that the user likes and products that have a tag (through the inner join):
var tblProductListOfLikedProductsForUser = (from p in repo.Products
join tag in repo.ProductTags on p.ProductId equals tag.ProductId // as you are not retrieving tag info this is only usefull if you want to ensure that each product has a tag
join l in repo.LikedProducts on new { p.ProductId, userId } equals new { l.ProductId, l.UserId } // limits products to those the user likes
// join u in repo.Users on l.UserId equals u.UserId // no benifit in using Users if you dont want user info and already have a userid
where productIdList.Contains(p.ProductId)
select p).ToList();
If productId and UserId data exist than return true otherwise false).
Here is a modified query that would return a list of product ids for those that the user likes and are in the list. The joins would only ensure that the product exists in all the tables (i have no idea what the referential integrity is of the db, if there are FK constraints defined you can get rid of the join on products).
var productIdsLikedProductsForUser = (from p in repo.Products // ensure the product exists
join tag in repo.ProductTags on p.ProductId equals tag.ProductId // ensure the product has a tag
join l in repo.LikedProducts on new { p.ProductId, userId } equals new { l.ProductId, l.UserId } // limits products to those the user likes
where productIdList.Contains(l.ProductId)
select l.ProductId).ToList();
If you do not care about that then you do not need a complex join, just query the LikedProducts table directly.
var productIdsLikedProductsForUser = (from l in repo.LikedProducts
where productIdList.Contains(l.ProductId)
&& l.UserId == userId
select l.ProductId).ToList();
As Products table contains UserId(FK reference of Users table) so Is it possible to include UserName, FirstName, LastName from Users Table?
Yes, you can use a group by clause.
var userWithLikedProducts = (from l in repo.LikedProducts
join u in repo.Users on l.UserId equals u.UserId
where productIdList.Contains(l.ProductId)
&& l.UserId == userId
group l.ProductId by new { u.UserName, u.FirstName, u.LastName } into productGroup
select new { User = productGroup.Key, LikedProductIds = productGroup.Select(x => x) }).SingleOrDefault();

Querying tables with count from other tables

I have three tables in database that are "UserGroup" which has a unique group for user. The second table is "Users" that has users but multiple users can belong to same usergroup.
Similarly I have a third table "Roles" that contains roles and multiple roles
can belong to same "usergroup".
Therefore parent table is UserGroup the id of this table is foreign key in two other tables.
A related question has been already asked here but if you can answer with my scenario , it would be better
Select from one table with count from two other tables
I am trying to query these tables such that I need count of "user Group" from
each of the two tables i.e from "users" and roles". If you can help with the Linq query, it would be appreciated.
For example:
"User Group Table"
Id GroupName
1 Admin
2 IT
3 Helpdesk
"Users Table"
Id USerGroupId UserName
1 1 Tom
2 1 Mickey
3 2 John
4 3 Sandy
"Roles Table"
Id USerGroupId Role
1 2 Supervisor
2 2 Superidetendent
3 3 etc
4 3 etc
Output should show:
GroupName USerCount RolesCount
Admin 2 0
IT 1 2
Helpdesk 1 2
SELECT GroupName
,(SELECT COUNT*) FROM Users U WHERE U.USerGroupId=G.Id) [USerCount]
,(SELECT COUNT*) FROM Roles r WHERE R.USerGroupId=G.Id) [RolesCount]
FROM Group g
I think something like that should work:
UsersTable.GroupBy(u => u.USerGroupId).Select(group => new {
USerGroupId = group.Key,
Count = group.Count()
}).OrderBy(x => x.USerGroupId);
RolesTable.GroupBy(u => u.USerGroupId).Select(group => new {
USerGroupId = group.Key,
Count = group.Count()
}).OrderBy(x => x.USerGroupId);
This is the linq to Entity in c# (if you use Entity Framework to connect to DB)
var query =
from h in (
(from b in db.UserTable
group b.UserGroup by new {
b.UserGroup.GroupName
} into g
select new {
g.Key.GroupName,
UserCount = g.Count(p => p.GroupName != null)
}))
join k in (
(from d in db.Roles
group d.UserGroup by new {
d.UserGroup.GroupName
} into g
select new {
g.Key.GroupName,
RolesCount = g.Count(p => p.GroupName != null)
})) on h.GroupName equals k.GroupName into k_join
from k in k_join.DefaultIfEmpty()
select new {
h.GroupName,
h.UserCount,
RolesCount = k.RolesCount
};
this is linq to SQL in c# (if you use DBML)
var query =
from h in (
(from a in db.UserGroup
join b in db.UserTable on new { Id = a.Id } equals new { Id = b.UserGroupId } into b_join
from b in b_join.DefaultIfEmpty()
group a by new {
a.GroupName
} into g
select new {
g.Key.GroupName,
UserCount = g.Count(p => p.GroupName != null)
}))
join k in (
(from d in db.Roles
group d.UserGroup by new {
d.UserGroup.GroupName
} into g
select new {
g.Key.GroupName,
RolesCount = g.Count(p => p.GroupName != null)
})) on h.GroupName equals k.GroupName into k_join
from k in k_join.DefaultIfEmpty()
select new {
h.GroupName,
h.UserCount,
RolesCount = k.RolesCount
};
this is the source SQL
SELECT h.GroupName, h.UserCount, k.RolesCount
FROM
(SELECT a.GroupName, count(a.GroupName) as UserCount
from UserGroup a
LEFT JOIN UserTable b on a.id = b.UserGroupId
group by a.GroupName) h
LEFT JOIN (
SELECT a.GroupName, count(a.GroupName) as RolesCount
from UserGroup a
INNER JOIN Roles d on a.id = d.UserGroupId
group by a.GroupName) k on h.GroupName = k.GroupName

SQL Server Simple Query

I have this tables on my database
Users,Courses,Semesters,SelectedCourses
Users : ID,Username,Password,EnterYear
Courses : ID,Name
Semesters : ID,Code
SelectedCourses : ID,SemesterID(FK to Semesters.ID),UserID(FK to Users.ID),CourseID(FK to Courses.ID)
Now, I have 2 or n CourseID and I want to get Users that selected this Courses together.
for example :
This is my SelectedCourses table :
Result must be :
I want to find Users that have CourseID(1) and CourseID(2) on their SelectedCourses list.
Only UserID = 1 have this two courses!
SELECT U.UserID
FROM Users U
WHERE NOT EXISTS ( SELECT C.CID
FROM Course C
WHERE C.CId in (1,2) AND
NOT EXISTS
(SELECT S.CID
FROM SelectedCourses S
WHERE S.CID = C.CID AND
S. UserID = U.UserID)
);
For each user we check that there is no course that is not taken by this user.
This works as long as the number of course is within the range of data type.
select
userId,count(distinct courseId)
from
selectedCourses
where
courseId in (1,2)
group by userId
having count(distinct courseId) > 1

Resources