Calculate average value per day based on single date column - sql-server

My data is as follows:
ID DATE_ADM DRUG_NAME DRUG_VALUE
2 2010-12-01 05:00:00.00 FORMULA VI 50
2 2010-12-01 10:30:00.00 FORMULA VI 40
2 2010-12-02 01:00:00.00 FORMULA V 20
1 2014-01-01 11:00:00.00 FORMULA V 40
1 2014-01-01 23:00:00.00 FORMULA IV 80
1 2014-01-02 11:00:00.00 FORMULA IV 80
I want to calculate the Average value per day for a similar drug name. So that I end up with a table as follows:
ID DATE_ADM DRUG_NAME DRUG_VALUE AVG_DAY_VALUE
2 2010-12-01 05:00:00.00 FORMULA VI 50 45
2 2010-12-01 10:30:00.00 FORMULA VI 40 45
2 2010-12-02 01:00:00.00 FORMULA V 20 20
1 2014-01-01 11:00:00.00 FORMULA V 40 60
1 2014-01-01 23:00:00.00 FORMULA IV 80 60
1 2014-01-02 11:00:00.00 FORMULA IV 80 80
Joel Coehoorn suggested the following to calculate the datediff, and I adapted it to something like this
datediff(day, date, coalesce(lag(date) over(partition by ID, DRUG_NAME order by id, date))) as day_diffs
avg(drug_value) over(partition by id, drug_name, day_diffs) as AVG_DAY_VALUE
No Luck so far. Any help would be appreciated.

Your desired results would seem to be just:
select *,
Avg(drug_value) over(partition by id, Convert(date,date)) Avg_Day_Value
from t
order by id desc, date;

Related

How to add values in sql

Hey i have a table like this
Product_name Rate Cost GST_percentage Recipt_no Amount Final_Amount ID Description GST_price Quantity OrderID Discount Net_Unit_Price Stock_Pending Payment_Pending
SINGTEL DATA + EZ $10 1.5 GB 7 DAYS 10 120.00 5 1 120.00 126 1 A 6.00 12 ODR1 0.00 10.00 Received Paid
SINGTEL DATA + EZ $10 1.5 GB 7 DAYS 12 180.00 0 2 180.00 180.00 2 A 0.00 15 ODR2 0.00 12.00 NULL NULL
SINGTEL DATA + EZ $8 CHINA 888 10 120.00 0 2 120.00 120.00 3 B 0.00 12 ODR2 0.00 10.00 NULL NULL
and i want to show the final_Amount column value groupped by order Id.then i want to show the final_amount for those which is Payment_Pending status is not null but i can't get the correct result.
Note:
i got a result as
query:
SELECT [OrderID],
SUM(convert(float,[Final_Amount])) as Final_Amount,
(select sum(convert(float,Final_Amount)) as Final_Amount
from Purchase_Order
where Payment_Pending is not null) as paid
FROM [Purchase_Order]
group by [OrderID]
order by OrderID desc
OrderID Final_Amount paid
ODR2 300 126
ODR1 126 126
but i want like this
OrderID Final_Amount paid
ODR2 300 0
ODR1 126 126
(Because ODR2 Payment_Pending Column filled with null)
Probably your sub-query is wrong. It need to include a reference to OrderId of main query
SELECT [OrderID],
SUM(convert(float,[Final_Amount])) as Final_Amount,
(select sum(convert(float,Final_Amount)) as Final_Amount
from Purchase_Order x
where x.Payment_Pending is not null
and x.OrderId = p.OrderId) as paid
FROM [Purchase_Order] p
group by [OrderID]
order by OrderID desc

Sql-Get time ranges from million+ rows for particular condition

I am working with SQL Server 2012, I have a table with approx 35 column and 10+ million rows.
I need to find time ranges from across the data where the value of any particular column is matching
E.g.
The sample data is as below
Datetime col1 col2 col3
2018-05-31 0:00 1 2 1
2018-05-31 13:00 2 2 2
2018-05-31 14:30 3 2 1
2018-05-31 15:00 4 3 1
2018-05-31 16:00 4 5 1
2018-05-31 17:00 3 2 2
2018-05-31 17:30 3 2 4
2018-05-31 18:00 2 2 4
2018-05-31 20:00 1 2 6
2018-05-31 21:00 2 2 3
2018-05-31 21:10 2 2 1
2018-05-31 22:00 1 6 3
2018-05-31 22:00 4 5 1
2018-05-31 23:59 4 7 2
Find the time range from data where col2 value =< 2, accordingly my expected result set is as below
Start Time End time Time Diff
2018-05-31 0:00 2018-05-31 14:30 14:30:00
2018-05-31 17:00 2018-05-31 21:10 4:10:00
I can achieved the same with below logic, but it's extremely slow
I get all rows and then
Order by date_Time
Scan the rows get the first row where exactly value is matching and record that timestamp as start time.
Scan further rows till i get the row where condition is breaking and record that timestamp as end time.
But as i have to play with huge no. Of rows, overall this will make my operation slow, any inputs or pseudo code to improve the same.
We can use a slightly modified difference in row number method here. The purpose of the first CTE labelled cte1 is to add a computed column which labels islands we want, having a col2 values <= 2, as 1 and everything else as 0. Then, we can compute the difference of two row numbers, and aggregate over the islands to find the starting and ending times, and the difference between those times.
WITH cte1 AS (
SELECT *,
CASE WHEN col2 <= 2 THEN 1 ELSE 0 END AS class
FROM yourTable
),
cte2 AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY Datetime) -
ROW_NUMBER() OVER (PARTITION BY class ORDER BY Datetime) rn
FROM cte1
)
SELECT
MIN(Datetime) AS [Start Time],
MAX(Datetime) AS [End Time],
CONVERT(TIME, MAX(Datetime) - MIN(Datetime)) AS [Time Diff]
FROM cte2
WHERE class = 1
GROUP BY rn
ORDER BY MIN(Datetime);
Demo

Reset a sum in a query when a date field changes month

I am currently executing the following query:
Select *, Balance = SUM(DailyReAdmits)
OVER (ORDER BY Date_Total ROWS UNBOUNDED PRECEDING)
From #AllReadmits
Which returns these results:
Date_Total DailyReAdmits Balance
2015-08-25 4 4
2015-08-26 8 12
2015-08-27 9 21
2015-08-28 3 24
2015-08-29 1 25
2015-08-30 4 29
2015-08-31 3 32
2015-09-01 5 37
However, when a new month starts, I would like the balance to start over again and look like this:
Date_Total DailyReAdmits Balance
2015-08-25 4 4
2015-08-26 8 12
2015-08-27 9 21
2015-08-28 3 24
2015-08-29 1 25
2015-08-30 4 29
2015-08-31 3 32
2015-09-01 5 5
How can I achieve this?
I supposed that you want partition by month, so try this:
SELECT *, Balance = SUM(DailyReAdmits)
OVER (PARTITION BY DATEPART(MM,Date_Total) ORDER BY Date_Total ROWS UNBOUNDED PRECEDING)
FROM #AllReadmits

How to remove duplicates in SQL Server

I have data looks like this:
Order No. Name Date Unit Price Freight
001 ABC 1-16 232 25
001 ABC 1-16 55 25
001 ABC 1-16 156 25
002 DEF 2-5 478 16
002 DEF 2-5 356 16
I am trying to let freight cost only show once in my table, the result would look like:
Order No. Name Date Unit Price Freight
001 ABC 1-16 232 25
001 ABC 1-16 55 0
001 ABC 1-16 156 0
002 DEF 2-5 478 16
002 DEF 2-5 356 0
Please help me with this
Here is a query to get what you want:
SELECT
order_no, name, theDate, unit_price,
case
when row_number() OVER (PARTITION by order_no ORDER BY order_no) = 1 then freight
else 0
end as freight
from yourTable
This looks at all rows for each order number and provides the row number. If it's row 1 of that order it uses the values of the freight column, otherwise it uses 0.
Note that I'm assuming that the freight value is the same across all rows for the same order number.

Fetch Only Last Entry by user daily

I am working on a small reporting application. I have two tables
Agent Table Data
AgentID AgentName
------- ---------
1001 ABC
1002 XYZ
1003 POI
1004 JKL
Report Table Data
ReportID AgentId Labor Mandays Amount SubmitDate
-------- ------- ----- ------- ------ ----------
1 1001 30 10 5000 11/12/2011
2 1001 44 18 8000 11/14/2011
3 1002 33 75 3022 11/12/2011
4 1001 10 10 1500 11/14/2011
5 1002 10 10 1800 11/14/2011
6 1001 10 10 1400 11/14/2011
7 1003 40 40 1500 11/14/2011
8 1003 40 40 1800 11/14/2011
I want to generate a report which gives us output like
ReportID AgentId Labor Mandays Amount SubmitDate
-------- ------- ----- ------- ------ ----------
1 1001 30 10 5000 11/12/2011
3 1002 33 75 3022 11/12/2011
6 1001 10 10 1400 11/14/2011
5 1002 10 10 1800 11/14/2011
8 1003 40 40 1800 11/14/2011
Thanks in Advance
You didn't mention what VERSION of SQL Server you're using - if you're on 2005 or newer, you can use a CTE (Common Table Expression) with the ROW_NUMBER function:
;WITH LastPerAgent AS
(
SELECT
AgentID, ReportID, Labor, Mandays, Amount, SubmitDate,
ROW_NUMBER() OVER(PARTITION BY AgentID,SubmitDate
ORDER BY ReportID DESC) AS 'RowNum'
FROM dbo.Report
)
SELECT
AgentID, ReportID, Labor, Mandays, Amount, SubmitDate,
FROM LastPerAgent
WHERE RowNum = 1
This CTE "partitions" your data by AgentID and SubmitDate, and for each partition, the ROW_NUMBER function hands out sequential numbers, starting at 1 and ordered by ReportID DESC - so the "last" row (with the highest ReportID) for each (AgentID, SubmitDate) pair gets RowNum = 1 which is what I select from the CTE in the SELECT statement after it.
PS: this doesn't work 100% on your input data, since you've not defined how to group and how to eliminate rows.... you might need to adapt this query a bit, based on your requirements...

Resources