Average calculation between three factors - sql-server

I need to calculate the average across the past 5 months(APR, MAY, JUN, JUL, AUG). I have 2 splits to consider: Region(6 regions in total) and Status (between Build and Flow-thru). Currently the data is in a weekly format so I rounded up the weeks to get monthly figures. How do i get the average monthly figure using with the two splits. The table looks something like this:
Region|Orders|BuildStatus|Months
GP |1 |Build |APR
GP |2 |Non-Build |APR
GP |1 |Build |MAY
GP |2 |Non-Build |MAY
PD |1 |Build |APR
PD |2 |Non-Build |APR
PD |1 |Build |MAY
PD |2 |Non-Build |MAY
It repeats with 5 other regions up until August.
Please assist with the correct calculation and if possible you can also suggest the query for it.
The Result should be:
Region|Avg_Orders|BuildStatus
GP |1 |Build
GP |2 |Non-Build
PD |1 |Build
PD |2 |Non-Build
The figures on the average should be the average of the 5 months.
Thanks

DECLARE #t TABLE(
Region NVARCHAR(2)
,Orders INT
,BuildStatus NVARCHAR(100)
,Months NVARCHAR(3)
)
INSERT INTO #t VALUES
('GP', 1,'Build', 'APR')
,('GP', 2,'Non-Build', 'APR')
,('GP', 1,'Build', 'MAY')
,('GP', 2,'Non-Build', 'MAY')
,('PD', 1,'Build', 'APR')
,('PD', 2,'Non-Build', 'APR')
,('PD', 1,'Build', 'MAY')
,('PD', 2,'Non-Build', 'MAY');
WITH cteAgg AS(
SELECT t.Region, t.BuildStatus, SUM(t.Orders) Orders, COUNT(DISTINCT t.Months) MonthsCount
FROM #t t
GROUP BY t.Region, t.BuildStatus
)
SELECT Region, Orders/MonthsCount AS Avg_Orders, BuildStatus
FROM cteAgg
ORDER BY 1

Related

Converting Data to Tenths and averaging values

so I have a table in thousandths of a mile like this:
id |fk |from |to |speed|score
1 |123|10.002|10.003|20 |10
2 |123|10.003|10.004|25 |11
3 |123|10.004|10.005|40 |44
4 |123|10.005|10.006|50 |23
5 |123|10.006|10.007|20 |54
6 |123|10.007|10.008|10 |24
7 |123|10.008|10.009|65 |24
8 |123|10.009|10.010|23 |24
9 |123|10.010|10.011|74 |56
10 |123|10.011|10.012|25 |43
11 |123|10.012|10.013|10 |76
12 |123|10.013|10.014|5 |10
...
I need to convert the thousandth mile table to tenths of a mile and take average of speed and score like this:
id |fk |from |to |Avgspeed|Avgscore
1 |123|10.002|10.012|35.2 |31.3
10 |123|10.012|... |... |...
I came up with this query to get the tenth of a mile:
select CASE WHEN rn=1 then 1
when rn%10=0 then 1
else 0 end chk,x.* from
(
select row_number() over (partition by fk order by fk,from) rn,* from dbo.Thous_Data
)x
This gives me
id |fk |from |to |speed|score|chk|rn
1 |123|10.002|10.003|20 |10 |1 |1
2 |123|10.003|10.004|25 |11 |0 |2
3 |123|10.004|10.005|40 |44 |0 |3
4 |123|10.005|10.006|50 |23 |0 |4
5 |123|10.006|10.007|20 |54 |0 |5
6 |123|10.007|10.008|10 |24 |0 |6
7 |123|10.008|10.009|65 |24 |0 |7
8 |123|10.009|10.010|23 |24 |0 |8
9 |123|10.010|10.011|74 |56 |0 |9
10 |123|10.011|10.012|25 |43 |1 |10
11 |123|10.012|10.013|10 |76 |0 |11
12 |123|10.013|10.014|5 |10 |0 |12
...
Not sure how to proceed with getting the averages and setting up the from and to correctly. Any ideas appreciated.
Something like this?
SELECT 10 * FLOOR(id / 10) , AVG(speed), MIN( [from] ) , MAX( [to])
FROM dbo.Thous_Data
GROUP BY 10 * FLOOR(id / 10);
The way I was able to do it was by starting the count from 0 so that the brackets would be accurate:
with cte as
(select CASE WHEN rn=0 then 1
when rn%10=0 then 1
else 0 end chk,x.*
from
(
select ROW_NUMBER() over (partition by fk order by fk,from)-1 rn,* from dbo.Thous_Data
)x
)
,cte2 as(
SELECT
distinct fk,to,from,
SUM([Chk]) OVER (PARTITION BY fk ORDER BY to,from) AS Groups
FROM cte
)
Select distinct fk,
Min(from) over (partition by fk,groups) from_
,Max(to) over (partition by fk,groups) to_
,avg(speed) over (partition by fk,groups) Aspeed
,avg(score) over (partition by fk,groups) Ascore
from
cte2

How to get latest salary of each associate in sql, table have month and year column also. each associate have minimum 4 to 5 records

Here is my query
Select distinct ASSOCIATE_ID,
Rate_Billed,
Currency,
RateMultiplier,
UOM,
MONTH,
YEAR= MAX(YEAR) over (partition by associate_id)
from asso_billinghrs
Below is the sample data.
|ASSOCIATE_ID |Rate_Billed | Currency| RateMultiplier| UOM |MONTH|YEAR|
|---------------|------------|----------|-----------------|-----|-----|----|
|1 |23.78 |USD |1 |B |11 |2013|
|1 |23.78 |USD |1 |B |2 |2014|
|1 |23.78 |USD |1 |B |3 |2014|
|2 |1 |INR |0.0146701 |C |1 |2017|
|2 |1 |INR |0.0147451 |C |1 |2017|
Below is the output
|ASSOCIATE_ID| Rate_Billed|Currency|RateMultiplier|UOM|MONTH|YEAR|
|------------|-------------|--------|--------------|---|-----|----|
|1 |23.78 |USD |1 |B |3 |2014|
|2 |1 |INR |0.0147451 |C |1 |2017|
Get latest salary of each associate in sql table having month and year column also. Each associate have minimum 4 to 5 records
Thanks
Try this :
WITH CTE AS(
Select distinct ASSOCIATE_ID,
Rate_Billed,
Currency,
RateMultiplier,
UOM,
MONTH,
YEAR,
ROW_NUMBER()over (partition by associate_id ORDER BY [YEAR],[MONTH] DESC) RN
from asso_billinghrs)
SELECT *
FROM CTE
WHERE RN=1
You may try using RANK() to get the following output.
select * from
(select *,RANK() over(partition by ASSOCIATE_ID order by tblyear desc,tblmonth desc,ratemultiplier desc)as r from asso_billinghrs)T
where r = 1
Output:
|ASSOCIATE_ID| Rate_Billed|Currency|RateMultiplier|UOM|MONTH|YEAR|
|------------|-------------|--------|--------------|---|-----|----|
|1 |23.78 |USD |1 |B |3 |2014|
|2 |1 |INR |0.0147451 |C |1 |2017|
FIDDLE

Using MAX in WHERE Clause with < -Operator

I want to select the entries in a table when the registration adress is equal to one (of more than one) delivery adresses AND this adress is the adress where the customer sent all his orders to this adress, since the adress was created.
Date 1 = Date of first order to specific adress, Date 2 = Last/Newest Order to specific adress.To make iot easier to understand... I´ve got this (Table1):
The task:
|cID ||company|Street |Code|del |Street2 |Cod2|Date 1 |Date 2 |
+------------------------------------------------------------------------+
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |DEL St.1|0212|01.01.2015|06.03.2015|
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |REF Wy.1|9875|26.02.2015|16.05.2015|
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |ABC Rd.1|4025|13.06.2015|08.08.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |DEL St.1|0212|13.03.2015|09.07.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |REG St.1|6754|21.02.2015|16.05.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |BLA Rd.5|0897|01.03.2015|06.12.2015|
|2 ||Ex2 |HIO Wy.1|9999|Ex2 |HIO Wy.1|9999|09.10.2015|26.11.2015|
|3 ||Ex3 |REG St.1|1114|Ex3 |DEL St.9|0212|13.01.2015|09.02.2015|
|3 ||Ex3 |REG St.1|1114|Ex3 |REG St.1|6754|21.03.2015|16.09.2015|
|3 ||Ex3 |REG St.1|1114|Ex3 |BLA Rd.5|0897|08.06.2015|06.08.2015|
|4 ||Ex4 |FAR RD.9|4567|Ex4 |DDR Wy.2|0897|01.03.2015|06.12.2015|
|4 ||Ex4 |FAR RD.9|4567|Ex4 |FAR RD.9|4567|09.10.2015|26.12.2015|
Expected Result
|cID ||company|Street |Code|del |Street |Code|Date 1 |Date 2 |
+------------------------------------------------------------------------+
|1 ||Ex1 |ABC Rd.1|4025|Ex1 |ABC Rd.1|4025|13.06.2015|08.08.2015|
respectively cID = 1
Here´s what I tried so far, but it´s not working....
SELECT cID
FROM Table1
WHERE company= del
AND Street = Street2
AND Code = Cod2
AND (SELECT MAX (Date 1) > (=! MAX(Date2) FROM Table1 Group by CID)
Edit (To make it more simple to understand):
e.g. the company with the name Ex1 (cID 1) is now located in ABC Rd.1|4025 (actual adress - the adress before is unknown) and has 3 adresses in system, where the orders of the company has been send to.
The first order on adress 1 (DEL St.1|0212) was on 01.01.2015,
the last order to this adress was on 06.03.2015.
The first order on adress 2 (REF Wy.1|9875) was on 26.02.2015
and the last order to this adress was on 16.05.2015 ...
-> I want the cID´s where registration adress (actual adress of the company) is the actual and only delivery adress.
Try using row number to get the latest date.
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER ( PARTITION BY Street, Code, company
ORDER BY Date1 DESC) as rn
FROM Table1
WHERE Street = Street2
AND Code = Cod2
AND company = del
) T
WHERE T.rn = 1
This should work:
SELECT cID
FROM Table1
WHERE Street = Street2
AND Code = Cod2
AND Date1 > (
SELECT MAX(Date2)
FROM Table1 as delivery
WHERE Table1.cID = delivery.cID
AND (delivery.Street2 <> Street OR delivery.Cod2 <> Code)
)
The subquery must itself be a correct SELECT-FROM-WHERE query, and a variable must be used to disambiguate between the outer and inner tables. The inner query selects all deliveries made to the same company but excluding the current delivery, and picks the maximal most recent date. It is then compared to the oldest date of the current delivery address.
Note that the data is not in second normal form. It may be worth, depending on the use case, splitting the table into a table with companies and a table with deliveries.
On my side, it returns 1 as expected.

Sum up delivered companies for every customer(ID)

I'm back in action ;) This time I have a pretty heavy task (I think).
Here's what I got:
|customerID ||company |compdel |Street |Code |Date 1 |Date 2 |
+-------------------------------+--------------------------------------+
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |01.01.2015 |01.08.2015 |
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |13.04.2015 |01.12.2015 |
|1 ||Example1 |DELExam2|DEL St.1|0212 |13.03.2015 |09.07.2015 |
|1 ||Example1 |DELExam3|REF Wy.1|9875 |26.05.2015 |16.09.2015 |
|2 ||Example2 |DELExam4|REG St.1|6754 |21.02.2015 |16.05.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.03.2015 |06.08.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.01.2015 |06.02.2015 |
I want to show for every customerID every delivered company (compdel) summed in one line with the earliest date in Date 1 and the newest Date in Date 2. To make it easier to understand, I want this result:
|customerID ||company |compdel |Street |Code |Date 1 |Date 2 |
+-------------------------------+--------------------------------------+
|1 ||Example1 |DELExam1|ABC Rd.1|4025 |01.01.2015 |01.12.2015 |
|1 ||Example1 |DELExam2|DEL St.1|0212 |13.03.2015 |09.07.2015 |
|1 ||Example1 |DELExam3|REF Wy.1|9875 |26.05.2015 |16.09.2015 |
|2 ||Example2 |DELExam4|REG St.1|6754 |21.02.2015 |16.05.2015 |
|2 ||Example2 |DELExam5|HIO Wy.1|9999 |01.01.2015 |06.08.2015 |
I tried it already with this select-Statement but it won´t work: I know, that this can only be a part of the answer....
SELECT *
FROM
(SELECT
customerID, company, compdel, Street, Code, Date 1, Date 2,
ROW_NUMBER() OVER(PARTITION BY compdel ORDER BY customerID) rn
FROM
table 1) as Y
WHERE
rn = 1
Use GROUP BY with distinct values (customerId, company etc.) and MIN and MAX for dates
SELECT CustomerId
, Company
, CompDel
, Street
, Code
, MIN(Date1) As EarliestDate1
, MAX(Date2) AS NewestDate2
FROM YourTable
GROUP BY CustomerId, Company, CompDel, Street, Code

How to get data for below scenario?

I have 4 tables.
Employee:
Id|emp_start_date|Public_id|
01|00-00-00 |001
02|00-00-00 |002
Person:
Id|Public_id|name|...
01|001 |aaaa|..
02|002 |bbbb|...
pay_info:
public_id|current_pay_year
001|2015
002|2015
Ni_table:
public_id|Ni_letter_code|Niable_pay|ni_a|ni_b|ni_c|ni_d|year
001 |A |890 |12 | 12 | 0 | 0 |2015
002 |A |500 |14 |14 |0 | 0 |2015
002 |A |600 |14 |14 |0 | 0 |2015
002 |B |400 |13 | 13 |0 |0 |2015
002 |B |500 |13 | 13 |0 |0 |2015
I want to get the Sum of niable_pay and all other columns by using ni_letter_code for the year 2015.
I want to get all the employees details for current pay year.
But When the employee has two ni letter code, then he should have 2 row for them.
Each row should have the addition value for the respective ni_code.
Expected output:
01|A| 890|12|12|0|0|2015
02|A|1100|25|28|0|0|2015
02|B| 900|26|26|0|0|2015
My query:
select
e.id,
NI.Ni_letter_code,
SUM(NI.Niable_pay),
SUM(ni_a),
SUM(ni_b),
SUM(ni_c),
SUM(ni_d),
ni.year
from
employee e
JOIN person P ON e.id=P.id
INNER JOIN pay_info PI ON PI.public_id = E.public_id
INNER JOIN Ni_table NI ON NI.public_id = E.public_id
AND NI.year = PI.current_pay_year
You seem to think that by stating
select
e.id,
NI.Ni_letter_code,
SUM(NI.Niable_pay),
SUM(ni_a),
SUM(ni_b),
SUM(ni_c),
SUM(ni_d),
ni.year
you get a result record per e.id, NI.Ni_letter_code and ni.year along with the desired sums.
This is not the case. SQL doesn't aggregate by non-aggregated columns implicitely. You must make the aggregation group explicit with GROUP BY. So in order to get one result record per e.id, NI.Ni_letter_code and ni.year you'd add:
group by e.id, NI.Ni_letter_code, ni.year
at the end of your query:
select
e.id,
NI.Ni_letter_code,
SUM(NI.Niable_pay),
SUM(ni_a),
SUM(ni_b),
SUM(ni_c),
SUM(ni_d),
ni.year
from
employee e
JOIN person P ON e.id=P.id
INNER JOIN pay_info PI ON PI.public_id = E.public_id
INNER JOIN Ni_table NI ON NI.public_id = E.public_id
AND NI.year = PI.current_pay_year
group by e.id, NI.Ni_letter_code, ni.year;

Resources