Count Unique Occurrences PowerPivot - powerpivot

I am new to PowerPivot and DAX formulas. I assume that what I am trying to do is very basic and it has probably been answered somewhere, I just don't know what to search on it find it.
I am trying to determine the percent of sales people who had a sale in a given quarters. I have two tables, one that lists the sales people and one that list all the sales for a quarter. For example
Employee ID
123
456
789
Sales ID - Emp ID - Amount
135645 ---- 123 ----- $50
876531 ---- 123 ----- $127
258546 ---- 123 ----- $37
516589 ---- 789 ----- $128
998513 ---- 789 ----- $79
As a result, the pivot table would look like this:
Emp ID - % w/ sales
123 -------- 100%
456 -------- 0%
789 -------- 100%
Total ------- 66%
If you can point me to a post where this has been addressed or let me know the best way to address this I would appreciate it. Thank you.

Here's a simple way of doing this (assuming table names emps and sales):
=IF (DISTINCTCOUNT ( sales[Emp ID] ) = BLANK (),
0,
DISTINCTCOUNT ( sales[Emp ID] )
)
/ COUNTROWS ( emps )
The IF() is only required to ensure that people who haven't made a sale appear in the Pivot. All the actual formula is doing is dividing the number of sales rows by the number of employee rows.
Jacob

You'll need to remove the text that begins with --. I wanted to describe what the DAX is doing. This may not do what you want because it only factors the employees in the context. E.x.: If the user filtered out all employees that didn't have sales, should the grand total be 100% or 66%? For the former, you'll need to use the ALL DAX function and the below DAX does the latter. I'm very new to DAX so I'm sure there's a better way to do what you want.
=IF
(
-- are we processing 1 employee or multiple employees? (E.x.: The grand total processes multiple employees...)
COUNTROWS(VALUES(employee[Employee ID])) > 1,
--If Processing multiple employees do X / Y
-- Where X = The number of employees that have sales
-- Where Y = The number of employees selected by the user
COUNTROWS(FILTER(employee, NOT(ISBLANK(CALCULATE(COUNT(sales[Sales ID])))))) / COUNTROWS(employee),
-- If processing single employee, return 0 if they have no sales, and 1 if they have sales
IF
(
ISBLANK(CALCULATE(COUNT(sales[Sales ID]))),
0,
1
)
)

Related

SQL Query Totals

I'm trying to write a query that calculates the average profit per employee for several projects.
I have a table that has employee names, what project they are working on, and how much profit they bring to their specific project each day.
My first query gives 3 fields - The project name, the sum of all the profits the employees bring to the project, and the number of employees in the project.
My second query I am trying to display 2 fields - the project name and the average profit per employee that each project makes
SELECT SAYSquery.ProjectName, SUM(SAYSquery.Profit) AS SumOfProfit, Count(SAYSquery.[EmpFirstName]) AS NumberOfEmps
FROM SAYSquery
WHERE profit > 0
GROUP BY SAYSquery.ProjectName;
SELECT SAYSqueryNIPE.[ProjectName], SAYSqueryNIPE.[SumOfProfit]/[NumberOfEmps] AS total
FROM SAYSqueryNIPE
GROUP BY SAYSqueryNIPE.[ProjectName], SAYSqueryNIPE.[SumOfProfit]/[NumberOfEmps];
Unfortunately, my second query is giving me the same average profit for every project and I'm not sure why. Any help would be much appreciated.
EDIT:
Query 1 reads:
**Employee Name | Sell Rate | Renumeration | Profit (Sell-Renumeration) | Project Name**
Query 2 reads:
**PROJECT NAME | SumofProfit | NumberofEmployees**
Project X | $1500 | 3 employees
Query 3 reads:
**PROJECT NAME | TOTAL**
Project X | $500 (Average profit per employee)
The problem is in your first query where you count the number of employees. As written in the question, you are returning a count of rows, not employees who worked on the project. You need to use count distinct. I'd also recommend not counting on EmpFirstName. If you have more than one employee with the same first name, the query won't give you correct results. It would be better to use a unique employee identifier instead of their first name.
SELECT SAYSquery.ProjectName, SUM(SAYSquery.Profit) AS SumOfProfit,
Count(distinct SAYSquery.[EmpFirstName]) AS NumberOfEmps
FROM SAYSquery
WHERE profit > 0
GROUP BY SAYSquery.ProjectName
You could wrap the whole thing up into a single query instead of two or three, as described in your question.
SELECT SAYSquery.ProjectName, SUM(SAYSquery.Profit)/Count(distinct SAYSquery.[EmpFirstName]) AS AvgProfitPerEmployee
FROM SAYSquery
WHERE profit > 0
GROUP BY SAYSquery.ProjectName

oracle - sql query select max from each base

I'm trying to solve this query where i need to find the the top balance at each base. Balance is in one table and bases are in another table.
This is the existing query i have that returns all the results but i need to find a way to limit it to 1 top result per baseID.
SELECT o.names.name t.accounts.bidd.baseID, MAX(t.accounts.balance)
FROM order o, table(c.accounts) t
WHERE t.accounts.acctype = 'verified'
GROUP BY o.names.name, t.accounts.bidd.baseID;
accounts is a nested table.
this is the output
Name accounts.BIDD.baseID MAX(T.accounts.BALANCE)
--------------- ------------------------- ---------------------------
Jerard 010 1251.21
john 012 3122.2
susan 012 3022.2
fin 012 3022.2
dan 010 1751.21
What i want the result to display is calculate the highest balance for each baseID and only display one record for that baseID.
So the output would look only display john for baseID 012 because he has the highest.
Any pointers in the right direction would be fantastic.
I think the problem is cause of the "Name" column. since you have three names mapped to one base id(12), it is considering all three records as unique ones and grouping them individually and not together.
Try to ignore the "Name" column in select query and in the "Group-by" clause.
SELECT t.accounts.bidd.baseID, MAX(t.accounts.balance)
FROM order o, table(c.accounts) t
WHERE t.accounts.acctype = 'verified'
GROUP BY t.accounts.bidd.baseID;

Create an Access expression using multi-value Count() data

The data I have is in a few tables. Table 1 has:
[invoice] (key),
[invoice total], and
[associated assets] (multi-value linked to [assets] in table 2).
Table two includes:
[Assets] (key), and
other asset data fields.
What I need to do is take the invoice total and divide it by the number of assets that go into that price to determine the cost of each asset. I have used the count() function in a query to get the number of assets for each invoice, but I can't seem to use the data anywhere else.
I have created another query to use the expression
= [invoice total]/count([associated assets]
In queries, I keep getting an aggregate error and can't seem to make this work. I would like for the expression result to populate a field in table 1. I need help either setting up a working query to pull the data from, or a form item that will pull the data and auto-populate the field.
For a table named [Invoices]
invoice invoice total associated assets
------- ------------- -----------------
1 $3.00 bicycles
2 $5.00 bicycles, ham
3 $1.00
where [associated assets] is a multi-value lookup field against the table [Assets]
AssetID AssetName
------- ---------
1 bicycles
2 ham
The following query
SELECT
i.invoice,
i.inv_tot AS [invoice total],
i.assetCount,
IIf(i.assetCount=0, NULL, i.[invoice total]/i.assetCount) AS avgCostPerAsset
FROM
(
SELECT
Invoices.invoice,
Min(Invoices.[invoice total]) AS inv_tot,
Count(Invoices.[associated assets].Value) AS assetCount
FROM Invoices
GROUP BY Invoices.invoice
) i
produces the following result
invoice invoice total assetCount avgCostPerAsset
------- ------------- ---------- ---------------
1 $3.00 1 3
2 $5.00 2 2.5
3 $1.00 0

GROUP BY and aggregate function query

I am looking at making a simple leader board for a time trial. A member may perform many time trials, but I only want for their fastest result to be displayed. My table columns are as follows:
Members { ID (PK), Forename, Surname }
TimeTrials { ID (PK), MemberID, Date, Time, Distance }
An example dataset would be:
Forename | Surname | Date | Time | Distance
Bill Smith 01-01-11 1.14 100
Dave Jones 04-09-11 2.33 100
Bill Smith 02-03-11 1.1 100
My resulting answer from the example above would be:
Forename | Surname | Date | Time | Distance
Bill Smith 02-03-11 1.1 100
Dave Jones 04-09-11 2.33 100
I have this so far, but access complains that I am not using Date as part of an aggregate function:
SELECT Members.Forename, Members.Surname, Min(TimeTrials.Time) AS MinOfTime, TimeTrials.Date
FROM Members
INNER JOIN TimeTrials ON Members.ID = TimeTrials.Member
GROUP BY Members.Forename, Members.Surname, TimeTrials.Distance
HAVING TimeTrials.Distance = 100
ORDER BY MIN(TimeTrials.Time);
IF I remove the Date from the SELECT the query works (without the date). I have tried using FIRST upon the TimeTrials.Date, but that will return the first date which is normally incorrect.
Obviously putting the Date as part of the GROUP BY would not return the result set that I am after.
Make this task easier on yourself by starting with a smaller piece of the problem. First get the minimum Time from TimeTrials for each combination of MemberID and Distance.
SELECT
tt.MemberID,
tt.Distance,
Min(tt.Time) AS MinOfTime
FROM TimeTrials AS tt
GROUP BY
tt.MemberID,
tt.Distance;
Assuming that SQL is correct, use it in a subquery which you join back to TimeTrials again.
SELECT tt2.*
FROM
TimeTrials AS tt2
INNER JOIN
(
SELECT
tt.MemberID,
tt.Distance,
Min(tt.Time) AS MinOfTime
FROM TimeTrials AS tt
GROUP BY
tt.MemberID,
tt.Distance
) AS sub
ON
tt2.MemberID = sub.MemberID
AND tt2.Distance = sub.Distance
AND tt2.Time = sub.MinOfTime
WHERE tt2.Distance = 100
ORDER BY tt2.Time;
Finally, you can join that query to Members to get Forename and Surname. Your question shows you already know how to do that, so I'll leave it for you. :-)

SQL Query Advice - Most recent item

I have a table where I store customer sales (on periodicals, like newspaper) data. The product is stored by issue. Example
custid prodid issue qty datesold
1 123 2 12 01052008
2 234 1 5 01022008
1 123 1 5 01012008
2 444 2 3 02052008
How can I retrieve (whats a faster way) the get last issue for all products, for a specific customer? Can I have samples for both SQL Server 2000 and 2005? Please note, the table is over 500k rows.
Thanks
Assuming that "latest" is determined by date (rather than by issue number), this method is usually pretty fast, assuming decent indexes:
SELECT
T1.prodid,
T1.issue
FROM
Sales T1
LEFT OUTER JOIN dbo.Sales T2 ON
T2.custid = T1.custid AND
T2.prodid = T1.prodid AND
T2.datesold > T1.datesold
WHERE
T1.custid = #custid AND
T2.custid IS NULL
Handling 500k rows is something that a laptop can probably handle without trouble, let alone a real server, so I'd stay clear of denormalizing your database for "performance". Don't add extra maintenance, inaccuracy, and most of all headaches by tracking a "last sold" somewhere else.
EDIT: I forgot to mention... this doesn't specifically handle cases where two issues have the same exact datesold. You might need to tweak it based on your business rules for that situation.
Generic SQL; SQL Server's syntax shouldn't be much different:
SELECT prodid, max(issue) FROM sales WHERE custid = ? GROUP BY prodid;
Is this a new project? If so, I would be wary of setting up your database like this and read up a bit on normalization, so that you might end up with something like this:
CustID LastName FirstName
------ -------- ---------
1 Woman Test
2 Man Test
ProdID ProdName
------ --------
123 NY Times
234 Boston Globe
ProdID IssueID PublishDate
------ ------- -----------
123 1 12/05/2008
123 2 12/06/2008
CustID OrderID OrderDate
------ ------- ---------
1 1 12/04/2008
OrderID ProdID IssueID Quantity
------- ------ ------- --------
1 123 1 5
2 123 2 12
I'd have to know your database better to come up with a better schema, but it sound like you're building too many things into a flat table, which will cause lots of issues down the road.
If you're looking for most recent sale by date maybe that's what you need:
SELECT prodid, issue
FROM Sales
WHERE custid = #custid
AND datesold = SELECT MAX(datesold)
FROM Sales s
WHERE s.prodid = Sales.prodid
AND s.issue = Sales.issue
AND s.custid = #custid
To query on existing growing historical table is way too slow!
Strongly suggest you create a new table tblCustomerSalesLatest which stores the last issue data of each customer. and select from there.