Sum when column values match - sum

How can I sum all of the everything in the amount column if values in policy number column match. This is my current code, but it doesn't work.
select total.*
from (
select p.policyNum,
p.stateID,
p.effectiveDate,
a.claimFreeDiscount,
a.homeownerDiscount,
a.policyZip,
mb.claimnumber,
sum(mb.amount)
from aggressive.dbo.Policy as p
inner join Aggressive.dbo.Auto as a
on p.policyID = a.policyID
left join MicrosoftPowerBI.dbo.ClaimTransactionDetail as mb
on p.policyid = mb.policyid
where p.stateID = 74 and
p.companyID = 10 and
p.status =1
) as total
group by total.mb.Amount

Related

SQL joins not giving me correct totals

I'm trying to get a report for figures from multiple transaction tables. Each table has a foreign key that is a lookup for the day it was taken on, and what location it was taken at called Site_Lookup_Id. It's giving me figures that are much larger than they should be.
#Site_Lookup_Ids dbo.Id_List READONLY
SELECT SL.Site_Lookup_Id, D.[Start],SUM(I.Amount) AS Income,
SUM(P.Amount) AS Payouts,SUM(DP.Amount) AS Deposit
FROM CashUp_Site_Lookup SL
INNER JOIN #Site_Lookup_Ids IDs ON Ids.Id = SL.Site_Lookup_Id
INNER JOIN CashUp_Day D ON SL.Day_Id = D.Day_Id
LEFT JOIN CashUp_Deposit DP ON DP.Redeemed_Site_Lookup_Id = SL.Site_Lookup_Id
AND DP.No_Show != 1
LEFT JOIN CashUp_Income I ON I.Site_Lookup_Id = SL.Site_Lookup_Id
LEFT JOIN CashUp_Payout P ON P.Site_Lookup_Id = SL.Site_Lookup_Id
GROUP BY SL.Site_Lookup_Id, D.[Start]
Not all sums will have a value as some days no transactions for a given table will be taken on the day - In this the value should be zero.
The issue is that running this gives me crazy high values - £7500 for income against one day, when if I do a simple check it's £40 for that day like so.
SELECT SUM(Amount) FROM Cashup_Income WHERE Site_Lookup_Id IN (values...)
Maybe something like...
It really depends on the relationships and when you want the values to be summed.
SELECT SL.Site_Lookup_Id
, D.[Start]
, SUM(I.Amount) over (partition by Key of I table) AS Income
, SUM(P.Amount) over (partition by Key of P table) AS Payouts
, SUM(DP.Amount) over (partition by Key of DP Table) AS Deposit
FROM CashUp_Site_Lookup SL
INNER JOIN #Site_Lookup_Ids IDs ON Ids.Id = SL.Site_Lookup_Id
INNER JOIN CashUp_Day D ON SL.Day_Id = D.Day_Id
LEFT JOIN CashUp_Deposit DP ON DP.Redeemed_Site_Lookup_Id = SL.Site_Lookup_Id
AND DP.No_Show != 1
LEFT JOIN CashUp_Income I ON I.Site_Lookup_Id = SL.Site_Lookup_Id
LEFT JOIN CashUp_Payout P ON P.Site_Lookup_Id = SL.Site_Lookup_Id
GROUP BY SL.Site_Lookup_Id, D.[Start]
The problem stems from the fact that your tables are 1:M Causing values to repeat. These repeated values are then getting added to your sum. The joins cause this issue. So I think you can sum using a partition to eliminate the duplicates or:
Use derived tables or a CTE and sum the values BEFORE you join.
Using CTE's (Common Table Expressions)
WITH DP AS (SELECT sum(Amount) As Deposit
, Redeemed_Site_Lookup_ID
FROM CashUp_Deposit
WHERE No_Show !=1
GROUP BY Redeemed_Site_Lookup_ID),
I AS (SELECT sum(Amount) as Income
, Site_Lookup_Id
FROM CashUp_Income
GROUP BY Site_Lookup_Id),
P AS (SELECT sum(Amount) as Payouts
, Site_Lookup_Id
FROM CashUp_Payout
GROUP BY Site_Lookup_Id)
SELECT SL.Site_Lookup_Id
, D.[Start]
, Income
, Payouts
, Deposit
FROM CashUp_Site_Lookup SL
INNER JOIN #Site_Lookup_Ids IDs
ON Ids.Id = SL.Site_Lookup_Id
INNER JOIN CashUp_Day D
ON SL.Day_Id = D.Day_Id
LEFT JOIN DP
ON DP.Redeemed_Site_Lookup_Id = SL.Site_Lookup_Id
LEFT JOIN I
ON I.Site_Lookup_Id = SL.Site_Lookup_Id
LEFT JOIN P
ON P.Site_Lookup_Id = SL.Site_Lookup_Id
Presumably, you are generating a Cartesian product with your joins. Because you have no filtering, do the aggregation before the joins:
LEFT JOIN
(SELECT DP.Redeemed_Site_Lookup_Id, SUM(DP.Amount) AS Deposit
FROM CashUp_Deposit DP
WHERE DP.No_Show != 1
GROUP BY DP.Redeemed_Site_Lookup_Id
) DP
ON DP.Redeemed_Site_Lookup_Id = SL.Site_Lookup_Id LEFT JOIN
(SELECT I.Site_Lookup_Id, SUM(I.Amount) AS Income
FROM CashUp_Income I
GROUP BY I.Site_Lookup_Id
) I
ON I.Site_Lookup_Id = SL.Site_Lookup_Id LEFT JOIN
(SELECT P.Site_Lookup_Id, SUM(P.Amount) AS Payout
FROM CashUp_Payout P
GROUP BY I.Site_Lookup_Id
) P
ON P.Site_Lookup_Id = SL.Site_Lookup_Id
Then adjust the rest of your query to remove the GROUP BY and SUM()s.

SQL: Linking a Count to a specific value through multiple tables

I'm trying to link a COUNT to a specific value across several tables in a SQL Server Database. In this case the tables only share values through correlation. I am returning the values I want but the COUNT is counting everything in a given project not just the ones linked to their work items.
SELECT
[d].[Id]
,COUNT([t].[ItemId]) AS ItemCount
,[d].[ItemName]
FROM
[dbo].[Project_Map] [rm] WITH (NOLOCK)
INNER JOIN
[dbo].[WorkProjects] [r] WITH (NOLOCK)
ON [r].[DomainId] = [rm].[DomainId]
AND [r].[ProjectId] = [rm].[ProjectId]
AND [r].[ReleaseId] = [rm].[ReleaseId]
INNER JOIN
[dbo].[Items] [d] WITH (NOLOCK)
ON [d].[DomainId] = [r].[DomainId]
AND [d].[ProjectId] = [r].[ProjectId]
AND [d].[ReleaseId] = [r].[ReleaseId]
INNER JOIN [dbo].[Projects] [p] with (NOLOCK)
ON r.DomainId = p.DomainId
AND r.ProjectId = p.ProjectId
INNER JOIN [dbo].[Tests] [t] with (NOLOCK)
ON p.DomainId = t.DomainId
AND p.ProjectId = t.ProjectId
INNER JOIN
(
SELECT [Id], MAX([LastModifiedDate]) AS MostRecent
FROM Items
Group By [Id]
) AS updatedItem
ON updatedItem.Id = d.Id
INNER JOIN
[dbo].[WorkItemStates] [ds] WITH (NOLOCK)
ON [ds].[ItemStateName] = [d].[ItemStatus]
WHERE
d.Id = 111111
AND d.UserCategory Like 'SOMESTRING'
GROUP BY d.Id, d.ItemName
RETURNS: In this case the count should be 1 but it returns the count for the entire project.
ID COUNT ITEMNAME
86 5169 SOME NAME
173 5169 SOME NAME
170 5169 SOME NAME
Am I missing a join somewhere?
Currently, your counts are counting all JOIN instances and not just distinct Item level records. Consider turning your Item unit level join into an aggregate query join and include the count field in outer grouping:
Specifically, change:
INNER JOIN [dbo].[Tests] [t] with (NOLOCK)
ON p.DomainId = t.DomainId
AND p.ProjectId = t.ProjectId
Into:
INNER JOIN
(SELECT t.DomaindId, t.ProjectId, Count(*) As ItemCount
FROM [dbo].[Tests] t
GROUP BY t.DomaindId, t.ProjectId) agg
ON p.DomainId = agg.DomainId
AND p.ProjectId = agg.ProjectId
And then the outer query structure becomes:
SELECT
[d].[Id]
,agg.ItemCount
,[d].[ItemName]
FROM
...
GROUP BY
[d].[Id]
,agg.ItemCount
,[d].[ItemName]
Interestingly, you already do such an aggregate query join but never use that derived table updateItem or the field MostRecent.

How to use group by only for some columns in sql Query?

The following query returns 550 records, which I am then grouping by some columns in the controller via linq. However, how can I achieve the "group by" logic in the SQL query itself? Additionally, post-grouping, I need to show only 150 results to the user.
Current SQL query:
SELECT DISTINCT
l.Id AS LoadId
, l.LoadTrackingNumber AS LoadDisplayId
, planningType.Text AS PlanningType
, loadStatus.Id AS StatusId
, loadWorkRequest.Id AS LoadRequestId
, loadStatus.Text AS Status
, routeIds.RouteIdentifier AS RouteName
, planRequest.Id AS PlanId
, originPartyRole.Id AS OriginId
, originParty.Id AS OriginPartyId
, originParty.LegalName AS Origin
, destinationPartyRole.Id AS DestinationId
, destinationParty.Id AS DestinationPartyId
, destinationParty.LegalName AS Destination
, COALESCE(firstSegmentLocation.Window_Start, originLocation.Window_Start) AS StartDate
, COALESCE(firstSegmentLocation.Window_Start, originLocation.Window_Start) AS BeginDate
, destLocation.Window_Finish AS EndDate
AS Number
FROM Domain.Loads (NOLOCK) AS l
INNER JOIN dbo.Lists (NOLOCK) AS loadStatus ON l.LoadStatusId = loadStatus.Id
INNER JOIN Domain.Routes (NOLOCK) AS routeIds ON routeIds.Id = l.RouteId
INNER JOIN Domain.BaseRequests (NOLOCK) AS loadWorkRequest ON loadWorkRequest.LoadId = l.Id
INNER JOIN Domain.BaseRequests (NOLOCK) AS planRequest ON planRequest.Id = loadWorkRequest.ParentWorkRequestId
INNER JOIN Domain.Schedules AS planSchedule ON planSchedule.Id = planRequest.ScheduleId
INNER JOIN Domain.Segments (NOLOCK) os on os.RouteId = routeIds.Id AND os.[Order] = 0
INNER JOIN Domain.LocationDetails (NOLOCK) AS originLocation ON originLocation.Id = os.DestinationId
INNER JOIN dbo.EntityRoles (NOLOCK) AS originPartyRole ON originPartyRole.Id = originLocation.DockRoleId
INNER JOIN dbo.Entities (NOLOCK) AS originParty ON originParty.Id = originPartyRole.PartyId
INNER JOIN Domain.LocationDetails (NOLOCK) AS destLocation ON destLocation.Id = routeIds.DestinationFacilityLocationId
INNER JOIN dbo.EntityRoles (NOLOCK) AS destinationPartyRole ON destinationPartyRole.Id = destLocation.DockRoleId
INNER JOIN dbo.Entities (NOLOCK) AS destinationParty ON destinationParty.Id = destinationPartyRole.PartyId
INNER JOIN dbo.TransportationModes (NOLOCK) lictm on lictm.Id = l.LoadInstanceCarrierModeId
INNER JOIN dbo.EntityRoles (NOLOCK) AS carrierPartyRole ON lictm.CarrierId = carrierPartyRole.Id
INNER JOIN dbo.Entities (NOLOCK) AS carrier ON carrierPartyRole.PartyId = carrier.Id
INNER JOIN dbo.EntityRoles (NOLOCK) AS respPartyRole ON l.ResponsiblePartyId = respPartyRole.Id
INNER JOIN dbo.Entities (NOLOCK) AS respParty ON respPartyRole.PartyId = respParty.Id
INNER JOIN Domain.LoadOrders (NOLOCK) lo ON lo.LoadInstanceId = l.Id
INNER JOIN Domain.Orders (NOLOCK) AS o ON lo.OrderInstanceId = o.Id
INNER JOIN Domain.BaseRequests (NOLOCK) AS loadRequest ON loadRequest.LoadId = l.Id
--Load Start Date
LEFT JOIN Domain.Segments (NOLOCK) AS segment ON segment.RouteId = l.RouteId AND segment.[Order] = 0
LEFT JOIN Domain.LocationDetails (NOLOCK) AS firstSegmentLocation ON firstSegmentLocation.Id = segment.DestinationId
LEFT JOIN dbo.Lists (NOLOCK) AS planningType ON l.PlanningTypeId = planningType.Id
LEFT JOIN dbo.EntityRoles (NOLOCK) AS billToRole ON o.BillToId = billToRole.Id
LEFT JOIN dbo.Entities (NOLOCK) AS billTo ON billToRole.PartyId = billTo.Id
WHERE o.CustomerId in (34236) AND originLocation.Window_Start >= '07/19/2015 00:00:00' AND originLocation.Window_Start < '07/25/2015 23:59:59' AND l.IsHistoricalLoad = 0
AND loadStatus.Id in (285, 286,289,611,290)
AND loadWorkRequest.ParentWorkRequestId IS NOT NULL
AND routeIds.RouteIdentifier IS NOT NULL
AND (planSchedule.EndDate IS NULL OR (planSchedule.EndDate is not null and CAST(CONVERT(varchar(10), planSchedule.EndDate,101) as datetime) > CAST(CONVERT(varchar(10),GETDATE(),101) as datetime))) ORDER BY l.Id DESC
linq:
//Get custom grouped data
var loadRequest = (from lq in returnList
let loadDisplayId = lq.LoadDisplayId
let origin = lq.OriginId //get this origin for route
let destination = lq.DestinationId // get this destination for route
group lq by new
{
RouteId = lq.RouteName,
PlanId = lq.PlanId,
Origin = lq.OriginId,
Destination = lq.DestinationId
}
into grp
select new
{
RouteId = grp.Key.RouteId,
PlanId = grp.Key.PlanId,
Origin = grp.Key.Origin,
Destination = grp.Key.Destination,
Loads = (from l in grp select l)
}).OrderBy(x => x.Origin).ToList();
I'm guessing you want to Group By column 1 but include columns 2 and 3 in your Select. Using a Group By you cannot do this. However, you can do this using a T-SQL Windowing function using the OVER() operator. Since you don't say how you want to aggregate, I cannot provide an example. But look at T-SQL Windowing functions. This article might help you get started.
One important thing you need to understand about GROUP BY is that you must assume that there are multiple values in every column outside of the GROUP BY list. In your case, you must assume that for each value of Column1 there would be multiple values of Column2 and Column3, all considered as a single group.
If you want your query to process any of these columns, you must specify what to do about these multiple values.
Here are some choices you have:
Pick the smallest or the largest value for a column in a group - use MIN(...) or MAX(...) aggregator for that
Count non-NULL items in a group - use COUNT(...)
Produce an average of non-NULL values in a group - use AVG(...)
For example, if you would like to find the smallest Column2 and an average of Column3 for each value of Column1, your query would look like this:
select
Column1, MIN(Column2), AVG(Column3)
from
TableName
group by
Column1

SQL Counting # of times a member shows up with certain code values

I am running a query that returns the location of a member and the product the member is enrolled in. Each time a member makes a claim with their product, they get a revenue code associated to them. Below is my query that I have now:
SELECT DISTINCT
e.State,
f.Product,
d.MemberID,
b.RevenueCode
FROM
Claims a
INNER JOIN
dw.Revenue b
ON
a.RevenueKey = b.RevenueKey
INNER JOIN
dw.Member d
ON
a.MemberKey = d.MemberKey
INNER JOIN
dw.Product f
ON
a.ProductKey = f.ProductKey
INNER JOIN
dw.State
ON
a.StateKey = f.StateKey
WHERE
b.RevenueCode IN ('0134', '0135')
It returns a set like the following:
State Product MemberID RevenueCode
MN xxx 945-234-245 0134
MN xxx 945-234-245 0135
SD xxx 231-345-235 0134
When a MemberID has both 0134 and 0135 RevenueCodes associated with it, they are considered to be in a special category. How would I modify my above query to count the number of times a MemberID has both RevenueCodes by State and by Product?
SELECT DISTINCT
e.State
,f.Product
,d.MemberID
,b.RevenueCode
,(SELECT 1
FROM Claims AS a1
INNER JOIN dw.Revenue AS b1 ON a1.RevenueKey = b1.RevenueKey
WHERE b1.RevenueCode IN ('0134', '0135')
AND b.revenuekey = b1.revenuekey
AND a.MemberKey = a1.Memberkey
HAVING COUNT(DISTINCT b1.RevenueCode) = 2) AS SpecialCategory
FROM Claims a
INNER JOIN dw.Revenue b ON a.RevenueKey = b.RevenueKey
INNER JOIN dw.Member d ON a.MemberKey = d.MemberKey
INNER JOIN dw.Product f ON a.ProductKey = f.ProductKey
INNER JOIN dw.State ON a.StateKey = f.StateKey
WHERE b.RevenueCode IN ('0134', '0135')
SELECT DISTINCT
e.State,
f.Product,
d.MemberID,
b.RevenueCode.
CASE WHEN EXISTS(
SELECT NULL
FROM Claims a1
JOIN dw.Revenue b1 ON a1.RevenueKey = b1.RevenueKey
JOIN dw.Member d1 ON a1.MemberKey = d1.MemberKey
JOIN dw.Product f1 ON a1.ProductKey = f1.ProductKey
WHERE b1.RevenueCode IN('0134', '0135') AND
d1.MemberID = d.MemberID AND
f1.ProductKey = f.ProductKey AND
f1.StateKey = f.StateKey
) THEN 1 ELSE 0 END As IsSpecialCategory
FROM
...
Figured it out...Simply needed to Count the Distinct RevenueCodes and Group By State, Product, and MemberID

How to make subqueries correct

Hey guys, I have some problem with subqueries in SQL. I am using MS Access 2010 and writing sql.
SELECT vak.Name, COUNT(vak.amount) AS [First], COUNT(vak2.amount2) AS [Second]
FROM
(SELECT kon.Name, (Count(icv.CV_ID) / Count(icv.CV_ID)) AS amount
FROM (kon INNER JOIN v ON kon.K_ID = v.K_ID) INNER JOIN icv ON v.Vak_ID = icv.Vak_ID
GROUP BY v.Vak_ID, kon.Name) AS vak,
(SELECT kon.Name, COUNT(v.Vak_ID) AS amount2
FROM (kon INNER JOIN v ON kon.K_ID = v.K_ID) INNER JOIN icv ON v.Vak_ID = icv.Vak_ID
GROUP BY kon.Name) AS vak2
GROUP BY vak.Konkursa_Nosaukums
When I check it in Datasheet view both columns are identical. There are 6 rows in "First" there are values 12, 12, 6, 12, 6, 6. Same values are in "Second" column. When I split this code into 2 pieces and make 2 new queries for testing, "First" Column shows values 2,2,1,2,1,1 and the second query has values of 3,3,1,2,1,1. Both of those columns have correct values when they are separately, but when I combine those, some unknown values appear like 12 (I have no idea where it take such number like 12). When I put line
WHERE vak.amount=vak2.amount2 before last line it shows 2,2,1,2,1,1 in both columns. I guess it takes only from first subquery or something.
How to make those subqueries correctly, so they show values same as when they are written separately?
I think you are missing a join condition and having in apropriate group by ...
SELECT vak.Name, vak.amount AS [First], vak2.amount2 AS [Second]
FROM
(SELECT kon.Name, (Count(icv.CV_ID) / Count(icv.CV_ID)) AS amount
FROM (kon INNER JOIN v ON kon.K_ID = v.K_ID) INNER JOIN icv ON v.Vak_ID = icv.Vak_ID
GROUP BY v.Vak_ID, kon.Name) AS vak,
(SELECT kon.Name, COUNT(v.Vak_ID) AS amount2
FROM (kon INNER JOIN v ON kon.K_ID = v.K_ID) INNER JOIN icv ON v.Vak_ID = icv.Vak_ID
GROUP BY kon.Name) AS vak2
WHERE vak.Name = van2.Name
SELECT vak.Name, vak.amount AS [First], vak2.amount2 AS [Second]
FROM
(SELECT kon.Name, (Count(icv.CV_ID) / Count(icv.CV_ID)) AS amount
FROM (kon INNER JOIN v ON kon.K_ID = v.K_ID) INNER JOIN icv ON v.Vak_ID = icv.Vak_ID
GROUP BY v.Vak_ID, kon.Name) AS vak,
(SELECT kon.Name, COUNT(v.Vak_ID) AS amount2
FROM (kon INNER JOIN v ON kon.K_ID = v.K_ID) INNER JOIN icv ON v.Vak_ID = icv.Vak_ID
GROUP BY kon.Name) AS vak2
WHERE vak.Name = van2.Name