Hourly sum of values - sql

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;

Related

I have a table of calls data I want to figure out the count Unique accounts called everyday and take sum of unique accounts called by monthly basis

I have a table with 2 unique columns one has an account number and the other is the date. The sample data is given below.
Date account
9/8/2020 555
9/8/2020 666
9/8/2020 777
9/8/2020 888
9/9/2020 555
9/9/2020 999
9/10/2020 555
9/10/2020 222
9/10/2020 333
9/11/2020 666
9/11/2020 111
I would like to calculate the number of unique accounts called every day and sum it up for a month for example if account number 555 is called on 8sept, p sept and 20 Sept its is not adding up to the cumulative sum the result should look like this
date Cumulative Unique Accounts Called SO Far this month
9/8/2020 4
9/9/2020 5
9/10/2020 7
9/11/2020 8
Thank you in advance for your help.
You can do this with aggregation and window functions. First, get the first date for each account, then aggregate and accumulate:
select min_date,
count(*) as as_of_date,
sum(count(*)) over (partition by year(min_datedate), month(min_datedate)
order by min_date
) as cumulative_unique_count
from (select account, min(date) as min_date
from t
group by account, year(date), month(date)
) t
group by min_date;
You can try the below -
with cte as
(
select date,count(*) as total from
(
select date,count,row_number() over(partition by count order by date) as rn
from tablename
)A where rn=1 group by date
)
select date,sum(total) over(order by date) as cum_sum
from cte

How to calculate +ve and -ve amounts on Totals in 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...

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

Firebird Query- Return first row each group

In a firebird database with a table "Sales", I need to select the first sale of all customers. See below a sample that show the table and desired result of query.
---------------------------------------
SALES
---------------------------------------
ID CUSTOMERID DTHRSALE
1 25 01/04/16 09:32
2 30 02/04/16 11:22
3 25 05/04/16 08:10
4 31 07/03/16 10:22
5 22 01/02/16 12:30
6 22 10/01/16 08:45
Result: only first sale, based on sale date.
ID CUSTOMERID DTHRSALE
1 25 01/04/16 09:32
2 30 02/04/16 11:22
4 31 07/03/16 10:22
6 22 10/01/16 08:45
I've already tested following code "Select first row in each GROUP BY group?", but it did not work.
In Firebird 2.5 you can do this with the following query; this is a minor modification of the second part of the accepted answer of the question you linked to tailored to your schema and requirements:
select x.id,
x.customerid,
x.dthrsale
from sales x
join (select customerid,
min(dthrsale) as first_sale
from sales
group by customerid) p on p.customerid = x.customerid
and p.first_sale = x.dthrsale
order by x.id
The order by is not necessary, I just added it to make it give the order as shown in your question.
With Firebird 3 you can use the window function ROW_NUMBER which is also described in the linked answer. The linked answer incorrectly said the first solution would work on Firebird 2.1 and higher. I have now edited it.
Search for the sales with no earlier sales:
SELECT S1.*
FROM SALES S1
LEFT JOIN SALES S2 ON S2.CUSTOMERID = S1.CUSTOMERID AND S2.DTHRSALE < S1.DTHRSALE
WHERE S2.ID IS NULL
Define an index over (customerid, dthrsale) to make it fast.
in Firebird 3 , get first row foreach customer by min sales_date :
SELECT id, customer_id, total, sales_date
FROM (
SELECT id, customer_id, total, sales_date
, row_number() OVER(PARTITION BY customer_id ORDER BY sales_date ASC ) AS rn
FROM SALES
) sub
WHERE rn = 1;
İf you want to get other related columns, This is where your self-answer fails.
select customer_id , min(sales_date)
, id, total --what about other colums
from SALES
group by customer_id
So simple as:
select CUSTOMERID min(DTHRSALE) from SALES group by CUSTOMERID

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.