SQL Count, counting Halfs! - sql-server-2005

I have a rather strange problem:
when certain sales are made (completed) a record is inserted with the event and ID of the sales person, currently this table is queried and the 'Count' is used (along with usual date boundaries) to calculate number of 'closed' sales. This is currently working fine.
The problem now is some sales are 'shared' sales, products are linked via leads, usually the lead and the product are always by the same sales person, however in some rare cases lead can be created by on salesperson and the product 'sold' by another in such case the 'sales' calculation needs to award 0.5 (half) a point to each sales person.
What would be the best SQL approach to solve this?
(SQL Server 2005)

SELECT
SUM(CASE WHEN SaleUserID = LeadUserID THEN 1 ELSE 0.5)
FROM
sales
WHERE
(SaleUserID = #targetID OR LeadUSerID = #targetID)
-- AND dateCriteria

Just use SUM() instead of COUNT(), i.e.
SELECT SUM(CASE WHEN shared=1 THEN 0.5 ELSE 1 END) FROM sales WHERE ...

I guess you have some way to distinguish between a "full sale" and a "half sale".
Count separately the number of "full sales" and the number of "half sales".
Then add full + 0.5*half.

Related

COUNT how many times a value appears and divide it by the number of total data

I need to write an SQL query that count the number of time a certain value appears, but then i need it to divide it by the total number of interventions (different table = dbo.gi3_intervention.gi3_n_intrvt) and multiply it by 100 to get the pourcentage.
I only know how to count the number of time the certain value appear, but I don't know how to do the division.
EDIT:
I need to divide it by the number of interventions that are closed since may first 2021. The intervention table is linked to the one stated above.
The intervention table = dbo.gi3_intervention.gi3_n_intrvt
the type should be '08', so dbo.gi3_intervention.GI3_C_TYPE_INTRVT = '08'
And should be closed since may 1st 2021, so dbo_GI3_INTERVENTION.GI3_D_CLOT_INTRVT = '>2021-05-01'
This is what I got:
SELECT count(*)
FROM dbo.gi3_note_intervention_appr_site
WHERE dbo.gi3_note_intervention_appr_site.gi3_c_sous_sujt_note = 'Etud tech Renseig add'
This answers the original version of the question.
You can use conditional aggregation. An elegant way (in my opinion) uses AVG():
SELECT AVG(CASE WHEN nias.gi3_c_sous_sujt_note = 'Etud tech Renseig add' THEN 100.0 ELSE 0 END) as percentage_etud
FROM dbo.gi3_note_intervention_appr_site nias

Calculation of weighted average counts in SQL

I have a query that I am currently using to find counts
select Name, Count(Distinct(ID)), Status, Team, Date from list
In addition to the counts, I need to calculate a goal based on weighted average of counts per status and team, for each day.
For example, if Name 1 counts are divided into 50% Status1-Team1(X) and 50% Status2-Team2(Y) yesterday, then today's goal for Name1 needs to be (X+Y)/2.
The table would look like this, with the 'Goal' field needed as the output:
What is the best way to do this in the same query?
I'm almost guessing here since you did not provide more details but maybe you want to do this:
SELECT name,status,team,data,(select sum(data)/(select count(*) from list where name = q.name)) FROM (SELECT Name, Count(Distinct(ID)) as data, Status, Team, Date FROM list) as q

Issue with finding out a percentage from the average in Postgres

Before I introduce my issue, I must specify that I am a beginner with SQL and Postgres.
I've made a database in Postgres, as a part of a project and I need to interrogate it. The database is about a firm which sells fertilizer.
One of the request is that I need to write a query that will return the Stores with Sales of 25% of the average of the total sales.
I have found out the average of the Sales by using the following query:
SELECT StoreID
FROM Sales
WHERE Price < (SELECT ROUND(AVG(Price)) FROM Sales);
Now, I don't know what should I put in the query to get the result.
Can anyone guide me?
If you mean sales with price below 25% of the average:
select storeid
from (
select storeid, price, avg(price) over() as avg_price
from sales
) s
where price < 0.25 * avg_price

Structuring Databases for Financial Statements

I am looking for the best way to structure my database. I have quarterly financial statements for 1000’s of companies from 1997-2012. Each company has three different statements, an income statement, a balance sheet, and a cash flow statement.
I want to be able to perform calculations on the data such as adding up each quarter to get a yearly total for each line item on each statement.
I have tried two ways so far:
1) Storing each line item for each statement in it’s own table i.e. Sales would be one table and have only sales data for all companies I am tracking, with company as the primary key, and each quarters data as a separate column. This seems like the easiest way to work with the data, but updating the data each quarter is time consuming as there are hundreds of tables.
Sales Table
Company q32012 q22012 q12012
ABC Co. 500 100 202
XYZ Co. 230 302 202
2) The other option which is a little easier to update but harder to work with the data is to have a separate table for each company for each statement. For example, the income statement for Royal Bank would have it’s own table, with the primary column being the line item.
Income Statement for Royal Bank
Line_Item q32012 q22012 q12012
Sales
Net Profit
The problem here is when I try to annualize this data, I get a really ugly output due to the group by
SELECT
(CASE WHEN Line_Item = 'Sales' THEN SUM(q4 + q3 + q2 + q1) ELSE '0' END) AS Sales2012,
(CASE WHEN Line_Item = 'NetProfit' THEN SUM(q4 + q3 + q2 + q1)
ELSE '0' END) AS Inventories2012
FROM dbo.[RoyalBankIncomeStatement]
GROUP BY Line_Item
Any help would be appreciated.
Whenever I've had to build a database for fiscal reports by fiscal quarter, month, or year or whatever, I've found it convenient to borrow a concept from star schema design and data warehousing, even if I'm not really building a DW.
The borrowed concept is to have a table, let's call it ALMANAC, that has one row for each date, keyed by the date. In this case a natural key works out well. Dependent attributes in here can be what fiscal month and quarter the date belongs to, whether the date was one where the enterprise was open for business (TRUE or FALSE), and whatever other quirks are in the company calendar.
Then, you need a computer program that just generates this table out of nothing. All the strange rules for the company calendar are embedded in this one program. The ALMANAC can cover a ten year period in a little over 3,650 rows. That's a tiny table.
Now every date in the operational data can be used like a foreign key into the ALMANAC table, provided you consistently use the Date datatype for dates. For example, each sale has a date of sale. Then aggregating by fiscal quarter, or fiscal year, or whatever you like is just a matter of joining operational data with the ALMANAC, and using GROUP BY and SUM() to get the aggregate you want.
It's simple, and it makes generating a whole raft of time period reports a breeze.
My advice to you is to think about not using a SQL database to do this. Instead, think of using something like SQL Server Analysis Services (SSAS). If you want to get a quick start with SSAS, I recommend getting up to speed on PowerPivot for Excel. You can take the model you develop in PowerPivot and import it into SSAS when you're ready.
Why don't I recommend SQL? Because you're going to have a problem aggregating accounts in SQL Server. For example, your balance sheets aren't going to be something you're going to be able to aggregate easily in SQL -- Asking SQL Server for the "Cash" for 2010, for example means that you want to get the entry for the end of December 2010, not that you want to SUM all of the entries for Cash for that year (which would be a nonsense number). On the other hand, with income and expense accounts such as those which would appear on your income statements, you would want to SUM those values up. To make matters worse, some reports are going to have a mix of account types on them, which is going to make reporting quite difficult.
SSAS has provisions inside the product where it "knows" how to aggregate for your reports based on account type, and there are many tutorials out there which can show you how to set this up.
Either way, you're going to need to store your data somewhere before it goes into your reporting system or Analysis Services cube. In order to do that, you should structure your data something like this. Let's say you're storing your data in a table called Reports:
Reports
--------
[Effective Date]
[CompanyID]
[AccountID]
[Amount]
Your Account table would have the description of what you're trying to store (income, expenses, etc). Your [Effective Date] column would link back into a Dates table which describes to which year, quarter, etc., your data belongs. In essence, what I'm describing is a classic shape for reporting databases, called a star schema.
I would probably go with the following structure in one data table:
Company
StatementType
LineItem
FiscalYear
Q1, Q2, Q3, Q4
StatementType would be Income Statement, Balance Sheet or Cash Flow Statement. Line Item would be the coded/uncoded text of the item on the statement, Fiscal Year is 2012, 2011 and so on. You'd still need to make sure that Line Items are consistent across companies.
This structure would let you query for flat statement -
select
LineItem, Q1, Q2, Q3, Q4
from Data
where
Company = 'RoyalBank'
and FiscalYear = 2012
and StatementType = 'Income Statement'
or
QoQ
select
FiscalYear,
Q1
from Data
where
Company = 'Royal Bank'
and
StatementType = 'Income Statement'
and
LineItem = 'Sales'
order by FiscalYear
in addition to aggregates. You'd probably want to have another table for line items with some kind of an index reference to make sure you can pull the statement back in the original order of line items.

sql average of a sum divided by a count

I am trying to do an SQL query to get the average spend for a specific customer.
I have written the following SQL (this is slighlty cut down for this example)..
SELECT SUM(price) as sumPrice, COUNT(transactionId) as transactionCount, customerName
FROM customers, transactions
WHERE customers.customerId = transactions.customerId
AND transactiontypeId = 1
GROUP BY customers.customerId
This gives me the sum of the transaction and the count. With this I can then divide the sum by the count to get the average spend. However I would like to be able to get the Average as a value straight out of the database rather than manipulate the data once I have got it out.
Is there any way to do this? I have played around with writing a select within a select but haven;t had much luck as of yet, hence asking on here.
Thanks in advance
MySQL has a mean average function built-in.
SELECT AVG(price) AS averageSpend, customerName
FROM customers, transactions
WHERE customers.customerId = transactions.customerId
AND transactiontypeId = 1
GROUP BY customers.customerId