How to calculate +ve and -ve amounts on Totals in SQL? - sql

The below Product table, Product ID - 100 as duplicated twice, and also there are negative profits are needs to Substract while calculating the Profit wise Total.
PID | Pname | Profit
100 AB 20
100 AB 20
101 BC 30
102 CD -10
103 DE -10
Expected Result: 30
Please provide the SQL query to get this result. Thanks in advance!!!

Is this what you want?
select sum(profit)
from (select distinct t.*
from t
) t

WITH CTE AS (
SELECT ROW_NUMBER() OVER (PARTITION BY PID ORDER BY PID ) AS rn,
PID,Pname,Profit FROM TableName
)
SELECT CAST(SUM(Profit) AS INT) AS Profit FROM CTE
WHERE rn=1
Note:- First you to get the DISTINCT Record then..use sum function...

Related

Top 2 Months of Sales by Customer - Oracle

I am trying to develop a query to pull out the top 2 months of sales by customer id. Here is a sample table:
Customer_ID Sales Amount Period
144567 40 2
234567 50 5
234567 40 7
144567 80 10
144567 48 2
234567 23 7
desired output would be
Customer_ID Sales Sum Period
144567 80 10
144567 48 2
234567 50 5
234567 40 7
I've tried
select sum(net_sales_usd_spot), valid_period, customer_id
from sales_trans_price_output
where valid_period in (select valid_period, sum(net_sales_usd_spot)
from sales_trans_price_output
where rank<=2)
group by valid_period, customer_id
error is
too many values ORA-00913.
I see why, but not sure how to rework it.
Try:
SELECT *
FROM (
SELECT t.*,
row_number() over (partition by customer_id order by sales_amount desc ) rn
FROM sales_trans_price t
)
WHERE rn <= 2
ORDER BY 1,2 desc
Demo: http://sqlfiddle.com/#!4/882888/3
what if you change your where clause to:
where valid_period in
(
select p.valid_period from sales_trans_price_output p
join (select valid_period, sum(net_sales_usd_spot)
from sales_trans_price_output
where rank<=2) s on s.valid_period = p.valid_period
)
It might be ugly and need refactoring, but I think this is the logic you're after.
The error is because of this.
where valid_period in (select valid_period, sum(net_sales_usd_spot)
from sales_trans_price_output
where rank<=2)
The subquery can only contain one field.
You are on the right track using rank, but you might not be using it correctly. Google oracle rank to find the correct syntax.
Back to what you are looking to achieve, a derived table is the approach I would use. That's simply a subquery with an alias. Or, if you use the keyword with, it might be called a CTE - Computed Table Expression.
Try it
SELECT * FROM (
SELECT T.*,
RANK () OVER (PARTITION BY CUSTOMER_ID
ORDER BY VALID_PERIOD DESC) FN_RANK
FROM SALES_TRANS_PRICE_OUTPUT T
) A
WHERE A.FN_RANK <= 2
ORDER BY CUSTOMER_ID ASC, VALID_PERIOD DESC, FN_RANK DESC

How do I calculate the accumulative percentage?

I have a table that consists of a customer ID, and the number of hours it took to place an order since they first registered.
An example would be:
UserId | TimeToPay
---------------------------------------------------
2DD6ABBB-C9A4-4373-B188-312DB8222859 | 0
C7438620-6431-4C13-B335-AA1A3E314C58 | 55
6AG22103-62B0-47A0-BE3F-7AE1A7A4C3B7 | 30
300A2E02-0799-47BB-BF36-070706F98149 | 8
43382839-E897-4E5F-A955-C9DDAF9B424B | 0
In the above example, 2 customers have placed an order within an hour of ordering something, and after 55 hours, all customers have placed an order. This table does not contain customers that have not placed an order yet. I am trying to create a query that shows cumulative percentages of how many customers have placed an order in what timespan. So my prefered output would be:
Hours | PercentageOfCustomers
-------------------------------
0 | 40
8 | 60
30 | 80
55 | 100
However, when I use answers like this or this one, I don't get cumulative percentages. How do I get my desired output?
You can use a windowed COUNT(*) to get a rolling total, and divide that by the number of total customers:
Select Distinct TimeToPay As Hours,
((Count(*) Over (Order By TimeToPay Asc) * 1.0) /
(Count(*) Over (Order By (Select Null)) * 1.0))
* 100 As PercentageOfCustomers
From Test
Order by Hours
Try This:
DECLARE #main_table TABLE ( UserId INT, TimeToPay INT)
INSERT INTO #main_table VALUES(1,0),(2,55),(3,30),(4,8),(5,0),(6,30),(7,30)
DECLARE #total INT = ( SELECT COUNT(col) FROM
( SELECT 'Z' col FROM #main_table GROUP BY TimeToPay )A GROUP BY col )
SELECT TimeToPay, (COUNT(TimeToPay)*100)/#total Percentage FROM #main_table
GROUP BY TimeToPay
Hope it helps. :)

How to get multiple rows based on max date

I have a table SalePrices in SQL server and data same as below:
SPID ProductID Price Date
001 Pro01 10 2016-03-10
002 Pro01 20 2016-03-11
003 Pro02 10 2016-03-13
004 Pro02 20 2016-03-15
What I want is create a view that show only one ProductID and Price that I have modified at the last time. So what I want is same as the result below:
ProductID Price Date
Pro01 20 2016-03-11
Pro02 20 2016-03-15
There're few different approaches for this, for example, using row_number():
;with cte as (
select
ProductID, Price, Date,
row_number() over(partition by ProductID order by Date desc) as rn
from <Table>
)
select
ProductID, Price, Date
from cte
where
rn = 1
sql fiddle demo
Another version with windowing functions, this one with FIRST_VALUE();
SELECT ProductID, price, date
FROM products
WHERE spid IN (
SELECT FIRST_VALUE(spid) OVER (PARTITION BY ProductID ORDER BY date DESC) spid
FROM products
)
An SQLfiddle to test with.
Note that Roman's version with ROW_NUMBER should work from SQL Server 2005 and newer, while this will only work for SQL Server 2012 and newer.
TRY THIS:
SELECT
ProductID
, Price
, Date FROM tablename AS A
JOIN (SELECT ProductID,MAX(Date) AS DATE FROM tablename
GROUP BY ProductID
) AS B ON A.Date=B.DATE AND A.ProductID=B.ProductID
one more approach...
select productid,price,date
from
table t1
where date=(select max(date) from table t2 where t1.productid=t2.productid)
Your last record will have the highest SPID:
select
ProductId, Price, Date
from
SalePrices sap
where
sap.spid =(
select
max(sap2.spid)
from
SalePrices sap2
where
sap2.productId = sap.productId)
This query will give u desired result:
ProductID Price Date
Pro01 20 2016-03-11
Pro02 20 2016-03-15

Hourly sum of values

I have a table with the following structure and sample data:
STORE_ID | INS_TIME | TOTAL_AMOUNT
2 07:46:01 20
3 19:20:05 100
4 12:40:21 87
5 09:05:08 5
6 11:30:00 12
6 14:22:07 100
I need to get the hourly sum of TOTAL_AMOUNT for each STORE_ID.
I tried the following query but i don't know if it's correct.
SELECT STORE_ID, SUM(TOTAL_AMOUNT) , HOUR(INS_TIME) as HOUR FROM VENDAS201302
WHERE MINUTE(INS_TIME) <=59
GROUP BY HOUR,STORE_ID
ORDER BY INS_TIME;
Not sure why you are not considering different days here. You could get the hourly sum using Datepart() function as below in Sql-Server:
DEMO
SELECT STORE_ID, SUM(TOTAL_AMOUNT) HOURLY_SUM
FROM t1
GROUP BY STORE_ID, datepart(hour,convert(datetime,INS_TIME))
ORDER BY STORE_ID
SELECT STORE_ID,
HOUR(INS_TIME) as HOUR_OF_TIME,
SUM(TOTAL_AMOUNT) as AMOUNT_SUM
FROM VENDAS201302
GROUP BY STORE_ID, HOUR_OF_TIME
ORDER BY INS_TIME;

Get max of column using sum

I have one table with following data..
saleId amount date
-------------------------
1 2000 10/10/2012
2 3000 12/10/2012
3 2000 11/12/2012
2 3000 12/10/2012
1 4000 11/10/2012
4 6000 10/10/2012
From my table I want result with max of sum amount between dates 10/10/2012 and 12/10/2012 which for the data above will be:
saleId amount
---------------
1 6000
2 6000
4 6000
Here 6000 is the max of the sums (by saleId) so I want ids 1, 2 and 4.
You have to use Sub-queries like this:
SELECT saleId , SUM(amount) AS Amount
FROM Table1
GROUP BY saleId
HAVING SUM(amount) =
(
SELECT MAX(AMOUNT) FROM
(
SELECT SUM(amount) AS AMOUNT FROM Table1
WHERE date BETWEEN '10/10/2012' AND '12/10/2012'
GROUP BY saleId
) AS A
)
See this SQLFiddle
This query goes through the table only once and is fairly optimised.
select top(1) with ties saleid, amount
from (
select saleid, sum(amount) amount
from tbl
where date between '20121010' and '20121210'
group by saleid
) x
order by amount desc;
You can produce the SUM with the WHERE clause as a derived table, then SELECT TOP(1) in the query using WITH TIES to show all the ones with the same (MAX) amount.
When presenting dates to SQL Server, try to always use the format YYYYMMDD for robustness.