calculation of balance after each transaction and opening bal - sql-server

I have two SQL Database table namely
Cust_Table(CustID, CustName, custAddrs, CustMob, CustOpBal)
And
Trans_Table(TransId, CustID, TransAmt, TransType(bool dr/cr), Msg, TansDate)
Now I need the SQL Query for getting Statement like (Bank Passbook) for a particular
Customer ID?
Date Message Dt_Amount Cr_Amount Balance
Iam using the following query
SELECT t1.Trans_Date, t1.Trans_Msg,
(CASE WHEN t1.Trans_Type=1 THEN 'Cr' ELSE 'Dr' END) as Trans_Type,
t1.Trans_Amount,
SUM(t2.Trans_Amount*case when t2.trans_type = '1' then 1 else -1 end) as Balance
FROM [LNLCredit].[dbo].[Trans_Table] t1
INNER JOIN [LNLCredit].[dbo].[Trans_Table] t2
ON t1.cust_id = t2.cust_id AND t1.trans_id >= t2.Trans_ID
WHERE t1.Cust_ID=2
GROUP BY t1.cust_id,t1.trans_id,t1.trans_type,t1.Trans_Amount,t1.Trans_Date,t1.Trans_Msg;
Its working fine.
But I also want to add Opening Balance (from Cust_Table) to the above solution.
Please Help??????

Try this..
SELECT t1.Trans_Date, t1.Trans_Msg,
(CASE WHEN t1.Trans_Type=1 THEN 'Cr' ELSE 'Dr' END) as Trans_Type,
t1.Trans_Amount,
SUM(t2.Trans_Amount*case when t2.trans_type = '1' then 1 else -1 end) as Balance,
c.CustOpBal
FROM [LNLCredit].[dbo].[Trans_Table] t1
INNER JOIN [LNLCredit].[dbo].[Trans_Table] t2
ON t1.cust_id = t2.cust_id AND t1.trans_id >= t2.Trans_ID
INNER JOIN Cust_Table C on C.cust_id = t1.cust_id
WHERE t1.Cust_ID=2
GROUP BY t1.cust_id,t1.trans_id,t1.trans_type,t1.Trans_Amount,
t1.Trans_Date,t1.Trans_Msg,C.CustOpBal;
You need to add an extra INNER JOIN and add openingBalance column to GROUP BY and SELECT

Related

Query in getting multiple duplicate rows in SQL Server

I have 2 tables Table1 and Table2 in which I want to get the total count of duplicate rows:
Expected output:
Query tested:
SELECT
t1.name,
t1.duplicates,
ISNULL(t2.active, 0) AS active,
ISNULL(t3.inactive, 0) AS inactive
FROM
(SELECT
t1.name, COUNT(*) AS duplicates
FROM
(SELECT c.name
FROM table1 c
INNER JOIN table2 as cd on cd.id = c.id)) t1
GROUP BY
name
HAVING
COUNT(*) > 1) t1
LEFT JOIN
(SELECT c.name, COUNT(*) AS active
FROM table1 c
WHERE name IN (SELECT c.name FROM table1 c)
GROUP BY c.name AND status = 'Active'
GROUP BY name) t2 ON t1.name = t2.name
LEFT JOIN
(SELECT c.name, COUNT(*) AS inactive
FROM table1 c
WHERE name IN (SELECT c.name FROM table1 c GROUP BY c.name)
AND status = 'InActive'
GROUP BY name) t3 ON t1.name = t3.name
ORDER BY
name
It is still returning duplicate rows and I'm unable to get the id and creator column
If you would pardon subquery and left join, i'd suggest the following query:
select b.*,
count(creator) as creator_count
from
(select a.mainid,
a.name,
sum(case when a.status = "active"
then 1 else 0 end) as active_count,
sum(case when a.status = "inactive"
then 1 else 0 end) as inactive_count,
count(a.name) as duplicate_count
from table1 as a
group by a.name
having count(a.name) > 1) as b
left join table2 as c
on b.mainid = c.mainid
group by c.mainid
having count(c.creator) > 1
rather than forcing our way to join the two table directly. First, derive the information we can get from the Table1 then join it with the Table2 to get the creator count.
SQL Fiddle: http://sqlfiddle.com/#!9/4daa19e/28

add a column to the select query which could be null

I would like to add another column to my select query called description inside posts table,
the problem is that this value could be null.
to make it clear, I have already linked foreign keys from tables Users, PostType and Votes.
Attaching the query:
SELECT po.id,
po.title,
CONVERT(varchar, po.pDate, 104) AS pDate,
pt.type,
us.userName,
SUM(CASE WHEN vt.isLike = 1 THEN 1 ELSE 0 END) AS upvotes,
SUM(CASE WHEN vt.isLike = 0 THEN 1 ELSE 0 END) AS downvotes
FROM Posts po
INNER JOIN PostType pt ON po.typeId = pt.id
INNER JOIN Users us ON po.userId = us.id
LEFT OUTER JOIN Votes vt ON vt.postId = po.id
GROUP BY po.id,
po.pDate,
po.title,
pt.type,
us.userName;
How to avoid group by null?
You can make that column non-nullable on the fly. So in the SELECT clause just add one more column to display CASE WHEN po.description IS NULL THEN 'present' ELSE 'absent' END AS description and repeat it in the GROUP BY clause CASE WHEN po.description IS NULL THEN 'present' ELSE 'absent' END
SELECT po.id,
po.title,
CASE WHEN po.description IS NULL THEN 'present' ELSE 'absent' END AS description,
CONVERT(varchar, po.pDate, 104) AS pDate,
pt.type,
us.userName,
SUM(CASE WHEN vt.isLike = 1 THEN 1 ELSE 0 END) AS upvotes,
SUM(CASE WHEN vt.isLike = 0 THEN 1 ELSE 0 END) AS downvotes
FROM Posts po
INNER JOIN PostType pt ON po.typeId = pt.id
INNER JOIN Users us ON po.userId = us.id
LEFT OUTER JOIN Votes vt ON vt.postId = po.id
GROUP BY po.id,
po.pDate,
po.title,
CASE WHEN po.description IS NULL THEN 'present' ELSE 'absent' END,
pt.type,
us.userName;

Subquery from another table in Case when condition

I am trying to write a query where I want to sum a price column based on the condition which is a subquery.
my query :
select
fund.FundName,
SUM(Case when (
Select Top 1 bitValue
from table 1
where table1.id = Company.id and table1.field = 25
) = 1 then price else 0 end) as 'TotalPrice'
from
Fund left outer join Company on Company.fundId=fund.id
group by
fund.fundName
It throws me error : Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
What is the best alternative way to achieve this.
Hope this Works for your Case:
SELECT
FUND.FUNDNAME,
S.TotalPrice
FROM FUND
LEFT OUTER JOIN COMPANY ON COMPANY.FUNDID=FUND.ID
LEFT JOIN (SELECT CASE WHEN BITVALUE=1 THEN SUM(PRICE) ELSE 0 END as 'TotalPrice',table1.ID
from table 1
where table1.id = Company.id and table1.field = 25 GROUP BY table1.ID
) S ON S.ID=Company.id
GROUP BY
FUND.FUNDNAME
untested obviously with no sample data provided.
select fund.FundName
,SUM(Case when table1.id is not null then price else 0 end) as 'TotalPrice'
from Fund
left outer join Company on Company.fundId = fund.id
left outer join (
select distinct id
from table1
where field = 25
and bitvalue = 1
) table1 on table1.id = Company.id
group by fund.fundName

SQL Server Overall Total in a group by

In my SQL Server Query, I am trying to count the number of employees per site. This works, but when I try to add in a percentage of total, it still groups by Site so it is inaccurate.
Is there an easier way to achieve this?
I am using this Query to create a view.
select Site.SiteName,
sum(case when Employee.ActiveStatus = 'Yes' then 1 else 0 end) as
"NumberOfEmployees",
CONVERT(decimal(6,2),(sum(case when Employee.ActiveStatus = 'Yes' then 1
else 0 end))/(convert(decimal(6,2),COUNT(EmployeeID)))) as PercentageOfEmps
from Employee
left join Site
on(Employee.SiteID=Site.SiteID)
GROUP BY Site.SiteName;
GO
You could use subquery:
select
Site.SiteName,
NumberOfEmployees = sum(case when Employee.ActiveStatus = 'Yes' then 1 else 0 end),
PercentageOfEmps = CONVERT(decimal(6,2),(sum(case when Employee.ActiveStatus = 'Yes' then 1
else 0 end))/(SELECT COUNT(EmployeeID) FROM Employee)
from Employee
left join Site
on Employee.SiteID=Site.SiteID
GROUP BY Site.SiteName;
I can't provide an answer for your scenario, as I don't have any sample data to use, therefore I've provided a small dataset.
One method is to use a CTE/Subquery to get a total number and then include the total in the GROUP BY. This method avoids 2 scans of the table:
WITH VTE AS(
SELECT *
FROM (VALUES(1,'Steve',1),
(2,'Jayne',1),
(3,'Greg',2),
(4,'Sarah',3)) V(EmpID, EmpName, SiteID)),
CTE AS(
SELECT V.EmpID,
V.EmpName,
V.SiteID,
COUNT(V.EmpID) OVER () AS TotalCount
FROM VTE V)
SELECT C.SiteID,
COUNT(C.EmpID) AS Employees,
COUNT(C.EmpID) / (C.TotalCount *1.0) AS Perc
FROM CTE C
GROUP BY C.SiteID,
C.TotalCount;
This script should help-
SELECT
Site.SiteName,
COUNT(EmployeeID) AS [NumberOfEmployees],
((COUNT(EmployeeID)*1.0)/(SELECT COUNT(*) FROM Employee WHERE ActiveStatus = 'Yes'))*100.00 as PercentageOfEmps
FROM Employee
INNER JOIN Site
ON Employee.SiteID = Site.SiteID
WHERE Employee.ActiveStatus = 'Yes'
GROUP BY Site.SiteName;
Data creation script
declare #Employee Table(EmployeeID int ,ActiveStatus nvarchar(20) ,SiteID int)
declare #Site Table(SiteName nvarchar(20) ,SiteID int)
insert into #Employee values(1,'Yes',101),(2,'Yes',101),(3,'Yes',102),(4,'Yes',102),
(5,'Yes',101)
insert into #Site values('Site1',101)
insert into #Site values('Site2',102)
//real script to get the %percentage
;with cte as
(
select s.SiteName,sum(case when e.ActiveStatus = 'Yes' then 1 else 0 end) as "NumberOfEmployees"
from #Employee e
left join #Site s
on(e.SiteID=s.SiteID)
GROUP BY s.SiteName
),
cte_sum as
(select sum(NumberOfEmployees) as total from cte )
select c.*, convert (decimal(6,2),c.NumberOfEmployees)/convert (decimal(6,2),cs.total)*100 from cte_sum cs, cte c;

how to add left join with CTE , check my query

i have following query i want add my query left join with CTE how do this please help me because i have driver id i want second last driver id but i want add left join with CTE
select d.Id,d.DriverNo,d.DriverName,TransId=dc.Id,dc.FromDate,dc.ToDate,dc.IsPaid,
Active=(case when (dc.weekoff is null or dc.weekoff=0) then 'Active' else 'Off' end),
Rent=(case when (IsNull(dc.CommissionTotal,0))> IsNull(dc.AccJobsTotal,0) then IsNull(dc.CommissionTotal,0)-(IsNull(dc.AccJobsTotal,0)) else 0 end),
BalanceDue=IsNull(dc.OldBalance,0),
AgentCommission=IsNull(dc.AgentFeesTotal,0),
PDA= (case when (dc.weekoff is null or dc.weekoff=0) then (IsNull(dc.PDARent,0)+IsNull(dc.CollectionDeliveryCharges,0)) else 0 end),
Total=(case when (IsNull(dc.CommissionTotal,0))> IsNull(dc.AccJobsTotal,0) then IsNull(dc.CommissionTotal,0)-(IsNull(dc.AccJobsTotal,0)) else 0 end)
+((IsNull(dc.OldBalance,0))
+((IsNull(dc.AgentFeesTotal,0)))
+(case when (dc.weekoff is null or dc.weekoff=0) then (IsNull(dc.PDARent,0)+IsNull(dc.CollectionDeliveryCharges,0)) else 0 end))
from Fleet_Driver d
inner join Fleet_DriverCommision dc
on d.Id=dc.DriverId
where dc.Id in (select Max(Id) from Fleet_DriverCommision
group by DriverId) as T1
left join on
> LEFT JOIN WITH CTE
With cte as
(select AgentFeesTotal,DriverId,Row_Number()over(Partition by DriverID order by Transdate desc) as Rn,
count(1)over(Partition by DriverID) as cnt from Fleet_DriverCommision)
Select AgentFeesTotal,DriverId
from cte
Where (Rn = 2 and cnt > 1) or (Rn = 1 and cnt = 1)
This is example
with cte
as
(select AgentFeesTotal,DriverId,Row_Number()over(Partition by DriverID order by Transdate desc) as Rn,
count(1)over(Partition by DriverID) as cnt from Fleet_DriverCommision)
Select AgentFeesTotal,DriverId
from cte
Where (Rn = 2 and cnt > 1) or (Rn = 1 and cnt = 1)
select t2.DriverNo from Fleet_Driver t2
left join
cte c
on c.DriverId=t2.Id
It looks like you are struggling with the syntax for using CTEs. The CTE declaration needs to happen before the rest of the query and then behaves like another table. Also note that the WITH statement must be the first statement or follow a semi-colon. This should get you on the right track. Also be sure to check the examples in the MSDN documentation.
--With statement first - must follow ; if there are multiple statements...
With cte as
(select AgentFeesTotal,DriverId,
Row_Number()over(Partition by DriverID order by Transdate desc) as Rn,
count(1)over(Partition by DriverID) as cnt
from Fleet_DriverCommision
)
-- ...then select statement...
select d.Id,d.DriverNo,d.DriverName,TransId=dc.Id,
dc.FromDate,dc.ToDate,dc.IsPaid,
Active=(case when (dc.weekoff is null or dc.weekoff=0) then 'Active' else 'Off' end),
Rent=(case when (IsNull(dc.CommissionTotal,0))> IsNull(dc.AccJobsTotal,0) then IsNull(dc.CommissionTotal,0)-(IsNull(dc.AccJobsTotal,0)) else 0 end),
BalanceDue=IsNull(dc.OldBalance,0),
AgentCommission=IsNull(dc.AgentFeesTotal,0),
PDA= (case when (dc.weekoff is null or dc.weekoff=0) then (IsNull(dc.PDARent,0)+IsNull(dc.CollectionDeliveryCharges,0)) else 0 end),
Total=(case when (IsNull(dc.CommissionTotal,0))> IsNull(dc.AccJobsTotal,0) then IsNull(dc.CommissionTotal,0)-(IsNull(dc.AccJobsTotal,0)) else 0 end)
+((IsNull(dc.OldBalance,0))
+((IsNull(dc.AgentFeesTotal,0)))
+(case when (dc.weekoff is null or dc.weekoff=0) then (IsNull(dc.PDARent,0)+IsNull(dc.CollectionDeliveryCharges,0)) else 0 end))
from Fleet_Driver d
inner join Fleet_DriverCommision dc
on d.Id=dc.DriverId
--...join in cte as a normal table
left join cte
on --join criteria here
where dc.Id in (select Max(Id) from Fleet_DriverCommision
group by DriverId) as T1
--move the remainder of the logic into your query
Select AgentFeesTotal,DriverId
from cte
Where (Rn = 2 and cnt > 1) or (Rn = 1 and cnt = 1)

Resources