Comparing in SQL and SUM - sql

I really couldn't figure out a good title for this question, but I have a problem that I'm sure you can help me with!
I have a query which outputs something like this:
Month | Year | Subcategory | PrivateLabel | Price
-------------------------------------------------
1 | 2010 | 666 | No | -520
1 | 2010 | 666 | No | -499,75
1 | 2010 | 666 | No | -59,95
1 | 2010 | 666 | No | -49,73
1 | 2010 | 666 | No | -32,95
I want to SUM on the price because all the other data is the same. I thought I could do this with SUM and GROUP BY, but I can't figure out how to do it or at least it doesn't output the right result.
The query is an inner join between two tables, if that helps.

select
month
,year
,subcategory
,privatelabel
,sum(price) as [total sales]
from
a inner join b ...
where
any where clauses
group by
month
,year
,subcategory
,privatelabel
should work if i am understanding you correctly.. every colum in the select either needs to be part of the group by or an aggregate function on all rows in the group
added a fiddle.. mainly as i didn't know about he text to DDL functionality and wanted to test it ;-) (thanks Michael Buen)
http://sqlfiddle.com/#!3/35c1c/1
note the where clause is a place holder..

select month, year, subcategory, privatelabel, sum(price)
from (put your query in here) dummyName
group by month, year, subcategory, privatelabel
Basic idea is it will run your current query to get above output then do the sum and group by on the result.
You query has to be in parentheses and you have to give it some name e.g. dummyName. As long as it's unique in the sql and preferably not a key word, doesn't matter what it is.
There might be a way of doing all this in one go, but without the sql for your query we can't help.

Related

Dividing sum results

I'm really sorry as this was probably answered before, but I couldn't find something that solved the problem.
In this case, I'm trying to get the result of dividing two sums in the same column.
| Id | month | budget | sales |
| -- | ----- | ------ | ----- |
| 1 | jan | 1000 | 800 |
| 2 | jan | 1000 | 850 |
| 1 | feb | 1200 | 800 |
| 2 | feb | 1100 | 850 |
What i want is to get the % of completition for each id and month (example: get 0,8 or 80% in a fifth column for id 1 in jan)
I have something like
sel
id,
month,
sum (daily_budget) as budget,
sum (daily_sales) as sales,
budget/sales over (partition by 1,2) as efectivenes
from sales
group by 1,2
I know im doing this wrong but I'm kinda new with sql and cant find the way :|
Thanks!
This should do it
CAST(ROUND(SUM(daily_sales) * 100.00 / SUM(daily_budget), 1) AS DECIMAL(5,2)) AS Effectiveness
I'm new at SQL too but maybe I can help. Try this?
sel
id,
month,
sum (daily_budget) as budget,
sum (daily_sales) as sales,
(sum(daily_budget)/sum(daily_sales)) over (partition by id) as efectivenes
from sales
group by id
If you want to ALTER your table so that it contains a fifth column where the result of budget/sales is automatically calculated, all you need to do this add the formula to this auto-generated column. The example I am about to show is based on MySQL.
Open MySQL
Find the table you wish to modify in the Navigator Pane, right-click on it and select "Alter Table"
Add a new row to your table. Make sure you select NN (Not Null) and G (Generated Column) check boxes
In the Default/Expression column, simply enter the expression budget / sales.
Once you run your next query, you should see your column generated and populated with the calculated results. If you simply want the SQL statement to do the same from the console, it will be something like this: ALTER table YOUR_TABLE_NAME add result FLOAT as (budget / sales);

SQL to find max of sum of data in one table, with extra columns

Apologies if this has been asked elsewhere. I have been looking on Stackoverflow all day and haven't found an answer yet. I am struggling to write the query to find the highest month's sales for each state from this example data.
The data looks like this:
| order_id | month | cust_id | state | prod_id | order_total |
+-----------+--------+----------+--------+----------+--------------+
| 67212 | June | 10001 | ca | 909 | 13 |
| 69090 | June | 10011 | fl | 44 | 76 |
... etc ...
My query
SELECT `month`, `state`, SUM(order_total) AS sales
FROM orders GROUP BY `month`, `state`
ORDER BY sales;
| month | state | sales |
+------------+--------+--------+
| September | wy | 435 |
| January | wy | 631 |
... etc ...
returns a few hundred rows: the sum of sales for each month for each state. I want it to only return the month with the highest sum of sales, but for each state. It might be a different month for different states.
This query
SELECT `state`, MAX(order_sum) as topmonth
FROM (SELECT `state`, SUM(order_total) order_sum FROM orders GROUP BY `month`,`state`)
GROUP BY `state`;
| state | topmonth |
+--------+-----------+
| ca | 119586 |
| ga | 30140 |
returns the correct number of rows with the correct data. BUT I would also like the query to give me the month column. Whatever I try with GROUP BY, I cannot find a way to limit the results to one record per state. I have tried PartitionBy without success, and have also tried unsuccessfully to do a join.
TL;DR: one query gives me the correct columns but too many rows; the other query gives me the correct number of rows (and the correct data) but insufficient columns.
Any suggestions to make this work would be most gratefully received.
I am using Apache Drill, which is apparently ANSI-SQL compliant. Hopefully that doesn't make much difference - I am assuming that the solution would be similar across all SQL engines.
This one should do the trick
SELECT t1.`month`, t1.`state`, t1.`sales`
FROM (
/* this one selects month, state and sales*/
SELECT `month`, `state`, SUM(order_total) AS sales
FROM orders
GROUP BY `month`, `state`
) AS t1
JOIN (
/* this one selects the best value for each state */
SELECT `state`, MAX(sales) AS best_month
FROM (
SELECT `month`, `state`, SUM(order_total) AS sales
FROM orders
GROUP BY `month`, `state`
)
GROUP BY `state`
) AS t2
ON t1.`state` = t2.`state` AND
t1.`sales` = t2.`best_month`
It's basically the combination of the two queries you wrote.
Try this:
SELECT `month`, `state`, SUM(order_total) FROM orders WHERE `month` IN
( SELECT TOP 1 t.month FROM ( SELECT `month` AS month, SUM(order_total) order_sum FROM orders GROUP BY `month`
ORDER BY order_sum DESC) t)
GROUP BY `month`, state ;

Adding another column based on different criteria (SQL-server)

I do quite a bit of data analysis and use SQL on a daily basis but my queries are rather simple, usually pulling a lot of data which I thereafter manipulate in excel, where I'm a lot more experienced.
This time though I'm trying to generate some Live Charts which have as input a single SQL query. I will now have to create complex tables without the aid of the excel tools I'm so familiar with.
The problem is the following:
We have telesales agents that book appointments by answering to inbound calls and making outbound cals. These will generate leads that might potentially result in a sale. The relevant tables and fields for this problem are these:
Contact Table
Agent
Sales Table
Price
OutboundCallDate
I want to know for each telesales agent their respective Total Sales amount in one column, and their outbound sales value in another.
The end result should look something like this:
+-------+------------+---------------+
| Agent | TotalSales | OutboundSales |
+-------+------------+---------------+
| Tom | 30145 | 0 |
| Sally | 16449 | 1000 |
| John | 10500 | 300 |
| Joe | 50710 | 0 |
+-------+------------+---------------+
With the below SQL I get the following result:
SELECT contact.agent, SUM(sales.price)
FROM contact, sales
WHERE contact.id = sales.id
GROUP BY contact.agent
+-------+------------+
| Agent | TotalSales |
+-------+------------+
| Tom | 30145 |
| Sally | 16449 |
| John | 10500 |
| Joe | 50710 |
+-------+------------+
I want to add the third column to this query result, in which the price is summed only for records where the OutboundCallDate field contains data. Something a bit like (where sales.OutboundCallDate is Not Null)
I hope this is clear enough. Let me know if that's not the case.
Use CASE
SELECT c.Agent,
SUM(s.price) AS TotalSales,
SUM(CASE
WHEN s.OutboundCallDate IS NOT NULL THEN s.price
ELSE 0
END) AS OutboundSales
FROM contact c, sales s
WHERE c.id = s.id
GROUP BY c.agent
I think the code would look
SELECT contact.agent, SUM(sales.price)
FROM contact, sales
WHERE contact.id = sales.id AND SUM(WHERE sales.OutboundCallDate)
GROUP BY contact.agent
notI'm assuming your Sales table contains something like Units and Price. If it's just a sales amount, then replace the calculation with the sales amount field name.
The key thing here is that the value summed should only be the sales amount if the OutboundCallDate exists. If the OutboundCallDate is not NULL, then we're using a value of 0 for that row.
select Agent.Agent, TotalSales = sum (sales.Price*Units)
, OutboundSales = sum (
case when Outboundcalldate is not null then price*Units
else 0
end)
From Sales inner join Agent on Sales.Agent = Agent.Agent
Group by Agent.Agent

SQL Server sum with a where or having condition

I'm hoping this makes sense as what I'm trying to do is SUM rows based on other columns of existing rows. I have tried a couple different ways and what I hope is now close is what I have here. This is not my full SQL but hopefully this small example will get me on track
SELECT Price,SUM(Item) from table where Price >= Price group by Price
Sample Data
| PRICE | ITEM |
|-------|-------|
| 1.00 | 5 |
| 2.00 | 9 |
| 3.00 | 2 |
Hopeful Result
| PRICE | ITEM |
|-------|-------|
| 1.00 | 5 |
| 2.00 | 14 |
| 3.00 | 16 |
The actual result is more or less the sample data which I would expect as I am grouping by Price so it makes sense that it returns the rows like this. I just can't seem to think of away to include Price in my select without having to group or use an aggregate on it. I'm thinking I could maybe do this type of calculation with an inner select but I'm hoping there is a different way as my actual query has a lot of joins which could get messy if I go this route.
Thanks for any help.
If you're using SQL server 2012...
Select price, item, sum(item) OVER(order by price rows unbounded preceding) as runningtotal
from sample
http://sqlfiddle.com/#!6/36e9f/1/0
You can accomplish this with a sub-query, but a more efficient way might be to use a CROSS/OUTER APPLY. It depends on your specific data. I provide both methods of doing that below... See which one runs faster based on your specific data.
Sub-query method
SELECT DISTINCT op.Price, (SELECT SUM(ip.Item) FROM table ip WHERE ip.Price <= op.Price) as ITEM FROM table op ORDER BY op.Price ASC
Outer-apply method
SELECT DISTINCT op.Price, a.Items
FROM table op
OUTER APPLY (SELECT SUM(ip.Item) as Items FROM TABLE ip WHERE ip.Price <= op.Price) a
ORDER BY op.Price ASC
Probably you are trying to do something like below. use a self join with the same table.
See a DEMO Here
SELECT t1.Price, SUM(t2.Item)
FROM table1 t1,
table1 t2
WHERE t2.Price <= t1.Price
GROUP BY t1.Price
ORDER BY t1.price;

SQL sum field when column values match

The title was hard to word but the question is pretty simple. I searched all over here and could not find something for my specific issue so here it is. I'm usuing Microsoft SQL Server Management Studio 2010.
Table Currently looks like this
| Value | Product Name|
| 300 | Bike |
| 400 | Bike |
| 300 | Car |
| 300 | Car |
I need the table to show me the sum of Values where Product Name matches - like this
| TOTAL | ProductName |
| 700 | Bike |
| 600 | Car |
I've tried a simple
SELECT
SUM(Value) AS 'Total'
,ProductName
FROM TableX
But the above doesn't work. I end up getting the sum of all values in the column. How can I sum based on the product name matching?
Thanks!
SELECT SUM(Value) AS 'Total', [Product Name]
FROM TableX
GROUP BY [Product Name]
SQL Fiddle Example
Anytime you use an aggregate function, (SUM, MIN, MAX ... ) with a column in the SELECT statement, you must use GROUP BY. This is a group function that indicates which column to group the aggregate by. Further, any columns that are not in the aggregate cannot be in your SELECT statement.
For example, the following syntax is invalid because you are specifying columns (col2) which are not in your GROUP BY (even though MySQL allows for this):
SELECT col1, col2, SUM(col3)
FROM table
GROUP BY col1
The solution to your question would be:
SELECT ProductName, SUM(Value) AS 'Total'
FROM TableX
GROUP BY ProductName