Good morning. SQL new guy here seeking some help. I'm attempting to get the AVG of my resultset from a subquery. The subquery works just fine and gives me the resultset I need, but I just cannot get the AVG of the resultset to work. Any guidance would be greatly appreciated.
SELECT AVG(COUNT) FROM
(SELECT COUNT(DISTINCT(table2.item_no))
FROM table1
JOIN table2 ON table1.order_numb = table2.order_numb
WHERE user_so = 'paul'
AND order_date BETWEEN '9/20/2017'AND '9/20/2018'
GROUP BY table1.order_numb);
Here is a sample of the resultset from the subquery on its own that I'm trying to then turn around and get an AVG of:
216
181
163
156
144
144
143
133
129
129
120
114
113
112
112
109
108
104
103
99
98
98
98
98
98
97
97
97
96
96
94
94
94
93
93
I think you want something like this:
SELECT AVG(a_number) FROM
(SELECT COUNT(DISTINCT(table2.item_no)) AS a_number
FROM table1
JOIN table2 ON table1.order_numb = table2.order_numb
WHERE user_so = 'paul'
AND order_date BETWEEN '9/20/2017'AND '9/20/2018'
GROUP BY table1.order_numb) AS the_subquery
I don't have the same tables with data, so here is a cut down working example:
SELECT AVG(a_number) FROM (
SELECT 100 AS a_number
UNION
SELECT 200 AS a_number
UNION
SELECT 300 AS a_number
UNION
SELECT 400 AS a_number
) AS the_subquery
It looks like you were missing that you need to alias the subquery and you want to AVG the alias of the value being returned in the subquery.
update
As per the comment, if you'd like the answer to be rounded to 2 decimal points you will need to CAST it to a different data type, like this:
SELECT ROUND(AVG(CAST(a_number AS FLOAT)), 2) FROM
(SELECT COUNT(DISTINCT(table2.item_no)) AS a_number
FROM table1
JOIN table2 ON table1.order_numb = table2.order_numb
WHERE user_so = 'paul'
AND order_date BETWEEN '9/20/2017'AND '9/20/2018'
GROUP BY table1.order_numb) AS the_subquery
or for others without access to the table:
SELECT ROUND(AVG(CAST(a_number AS FLOAT)), 2) FROM (
SELECT 100 AS a_number
UNION
SELECT 200 AS a_number
UNION
SELECT 300 AS a_number
UNION
SELECT 403 AS a_number
) AS the_subquery
You can read more about how ROUND, AVG, and CAST work here: How do I retrieve decimals when rounding an average in SQL
Related
I have a table t1
**id** **Date** **Sales**
102 20180101 50
102 20180102 60
102 20180103 70
102 20180104 90
102 20180105 10
102 20180105 100
102 20180106 100
102 20180107 30
102 20180108 20
102 20180109 34
102 20180110 40
102 20180111 50
102 20180112 60
Now I want the previous10 records for each row like for 20180111 sum of sale should be 464 which is the sum of the previous 10 records sale and for 20180112 it should be 474.
do you think the following is what you need ?
WITH temp
AS (SELECT id,
date,
SUM(sales) AS n_Sale
FROM dbo.t
GROUP BY id,
date)
SELECT *,
SUM(t.n_Sale) OVER (ORDER BY date ASC ROWS 9 PRECEDING)
FROM temp AS t;
I think you could add a consecutive index and then group by truncate(index/N), and get the sum of values.
for instance, to get the sum every 3 elements (mysql):
SELECT truncate((row_number-1)/3,0) grp, sum(sales) total
FROM (
SELECT #row_number:=#row_number+1 as row_number,
sales
FROM (
SELECT 452 as sales UNION ALL
SELECT 324 as sales UNION ALL
SELECT 342 as sales UNION ALL
SELECT 342 as sales UNION ALL
SELECT 342 as sales UNION ALL
SELECT 232 as sales
) as t1, (SELECT #row_number:=0) AS t2) as tf group by grp;
http://sqlfiddle.com/#!9/3149e4/524
I trying to create a table that will support a simple event study analysis, but I'm not sure how best to approach this.
I'd like to create a table with the following columns: Customer, Date, Time on website, Outcome. I'm testing the premise that the outcome for a particular customer on any give day if a function of the time spent on the website on the current day as well as the preceding five site visits. I'm envisioning a table similar to this:
I'm hoping to write a T-SQL query that will produce an output like this:
Given this objective, here are my questions:
Assuming this is indeed possible, how should I structure my table to accomplish this objective? Is there a need for a column that refers to the prior visit? Do I need to add an index to a particular column?
Would this be considered a recursive query?
Given the appropriate table structure, what would the query look like?
Is it possible to structure the query with a variable that determines the number of prior periods to include in addition to the current period (for example, if I want to compare 5 periods to 3 periods)?
Not sure I understand analytic value of your matrix
Declare #Table table (id int,VisitDate date,VisitTime int,Outcome varchar(25))
Insert Into #Table (id,VisitDate,VisitTime,Outcome) values
(123,'2015-12-01',100,'P'),
(123,'2016-01-01',101,'P'),
(123,'2016-02-01',102,'N'),
(123,'2016-03-01',100,'P'),
(123,'2016-04-01', 99,'N'),
(123,'2016-04-09', 98,'P'),
(123,'2016-05-09', 99,'P'),
(123,'2016-05-14',100,'N'),
(123,'2016-06-13', 99,'P'),
(123,'2016-06-15', 98,'P')
Select *
,T0 = VisitTime
,T1 = Lead(VisitTime,1,0) over(Partition By ID Order By ID,VisitDate Desc)
,T2 = Lead(VisitTime,2,0) over(Partition By ID Order By ID,VisitDate Desc)
,T3 = Lead(VisitTime,3,0) over(Partition By ID Order By ID,VisitDate Desc)
,T4 = Lead(VisitTime,4,0) over(Partition By ID Order By ID,VisitDate Desc)
,T5 = Lead(VisitTime,5,0) over(Partition By ID Order By ID,VisitDate Desc)
From #Table
Order By ID,VisitDate Desc
Returns
id VisitDate VisitTime Outcome T0 T1 T2 T3 T4 T5
123 2016-06-15 98 P 98 99 100 99 98 99
123 2016-06-13 99 P 99 100 99 98 99 100
123 2016-05-14 100 N 100 99 98 99 100 102
123 2016-05-09 99 P 99 98 99 100 102 101
123 2016-04-09 98 P 98 99 100 102 101 100
123 2016-04-01 99 N 99 100 102 101 100 0
123 2016-03-01 100 P 100 102 101 100 0 0
123 2016-02-01 102 N 102 101 100 0 0 0
123 2016-01-01 101 P 101 100 0 0 0 0
123 2015-12-01 100 P 100 0 0 0 0 0
With fixed columns you can do it like this with lag:
select
time,
lag(time, 1) over (partition by customer order by date desc),
lag(time, 2) over (partition by customer order by date desc),
lag(time, 3) over (partition by customer order by date desc),
lag(time, 4) over (partition by customer order by date desc)
from
yourtable
If you need dynamic columns, then you'll have to build it using dynamic SQL.
I have a table named PlayerScore that contains the player name and their average scores:
Id Name Average
1 Sakib 80
2 Tamim 70
3 Mushfiq 60
4 Sabbir 50
5 Ashraful 20
6 Aftab 40
7 Rubel 30
8 Kalu 10
I want to find their partnership combination based on a condition that,
palyer whose average score is greater than 40 can not be partner with players whose score is less than 40.
I tried the following query :
select a.Name,a.Average,b.Name,b.Average from ((select * from PlayerScore where Average<=40) as a inner join (select * from PlayerScore where Average<=40) as b on a.Id < b.Id)
union
select a.Name,a.Average,b.Name,b.Average from ((select * from PlayerScore where Average>=40) as a inner join (select * from PlayerScore where Average>=40) as b on a.Id < b.Id)
that results in :
Name Average Name Average
Aftab 40 Kalu 10
Aftab 40 Rubel 30
Ashraful 20 Aftab 40
Ashraful 20 Kalu 10
Ashraful 20 Rubel 30
Mushfiq 60 Aftab 40
Mushfiq 60 Sabbir 50
Rubel 30 Kalu 10
Sabbir 50 Aftab 40
Sakib 80 Aftab 40
Sakib 80 Mushfiq 60
Sakib 80 Sabbir 50
Sakib 80 Tamim 70
Tamim 70 Aftab 40
Tamim 70 Mushfiq 60
Tamim 70 Sabbir 50
Is their any solution without using UNION
select distinct a.Name,a.Average,b.Name,b.Average
from PlayerScore a
join PlayerScore b
on a.Id < b.Id
and ( a.Average<=40 and b.Average<=40
or a.Average>=40 and b.Average>=40
)
it will likely result in the same exceution plan.
Maybe you can do something like this:
SELECT
t.*,
t2.*
FROM
PlayerScore AS t
CROSS JOIN PlayerScore AS t2
WHERE t.Average>=40 AND t2.Average<40
ORDER BY t.Name
You can create 2 groups based on your condition and give them different values and then do a join based on the value. Something like this.
;WITH PlayerScore as
(
SELECT 1 AS Id,'Sakib' AS Name,80 AS Average
UNION ALL SELECT 2,'Tamim',70
UNION ALL SELECT 3,'Mushfiq',60
UNION ALL SELECT 4,'Sabbir',50
UNION ALL SELECT 5,'Ashraful',20
UNION ALL SELECT 6,'Aftab',40
UNION ALL SELECT 7,'Rubel',30
UNION ALL SELECT 8,'Kalu',10
),PlayerCriteria AS
(
SELECT *,CASE WHEN Average >= 40 THEN 1 ELSE 0 END joincondition
FROM PlayerScore
)
SELECT * FROM PlayerCriteria C1
INNER JOIN PlayerCriteria C2 ON C1.joincondition = C2.joincondition
AND C1.Id > C2.Id
i have on sql server 2008 table like
EmployeeCertificationHistoryId EmployeeCertificationID EmployeeID CertificationID CertificationDate
1 244 2192 1 2/15/2006
2 185 2058 87 4/10/2010
3 245 2240 102 8/11/2013
4 246 2249 104 11/23/2005
5 247 2221 101 6/12/2013
6 248 2238 84 NULL
7 245 2240 102 8/11/2013
8 249 2240 102 8/4/2013
10 253 2175 84 6/19/2013
11 254 2239 105 2/5/2011
12 255 2239 111 11/22/2012
9 96 1468 92 12/6/2010
13 256 2239 110 11/22/2012
i need to comma seperate certificationid per employeeid.
for eg. for 2239=>105,111,110
i have written a query but it is giving all certificate id in one column. my query is
SELECT STUFF(
(SELECT ',' + CAST(C.CertificationID AS VARCHAR(100))
FROM tbl_PM_EmployeeCertificationMatrixHistory C
ORDER BY c.CertificationID
FOR XML PATH('')),1,1,'') AS CSV
GO
i just need employeeid and certificationid.but i am unable to sort it out.
You need a correlated subquery and a list of employees. The following gets the list of employees from the same table but you might have another table with this information:
SELECT e.EmployeeID,
STUFF((SELECT ',' + CAST(C.CertificationID AS VARCHAR(100))
FROM tbl_PM_EmployeeCertificationMatrixHistory C
where c.EmployeeID = e.EmployeeID
ORDER BY c.CertificationID
FOR XML PATH('')
),1, 1,'') AS CSV
from (select distinct EmployeeID
from tbl_PM_EmployeeCertificationMatrixHistory
) e;
You just need to add EmployeeID to the query as well as a WHERE and DISTINCT
SELECT DISTINCT A.EmployeeID, STUFF(
(SELECT ',' + CAST(C.CertificationID AS VARCHAR(100))
FROM tbl_PM_EmployeeCertificationMatrixHistory C
WHERE C.EmployeeID = A.EmployeeID
ORDER BY c.CertificationID
FOR XML PATH('')),1,1,'') AS CSV
FROM tbl_PM_EmployeeCertificationMatrixHistory A
GO
If you want to return only DISTINCT values in the the CSV list, add GROUP BY c.CertificationID above the ORDER BY
I have the following source data (the data is an extract for a source of several hundred rows.):
ID CodeID Code
3749 69 354
3750 69 864
33721 130 XXX
33722 130 319
30446 159 XXX
30447 159 XXX
and using T-SQL I need to achieve:
CodeID Code1 Code2
69 354 864
130 XXX 319
159 XXX XXX
This doesn't seem to fit the structure for a pivot table and I have no idea how to achieve this. Does anyone have any suggestions.
You can do it with a pivot if you first assign each of the values a number using row_number()
select codeid, [1] as Code1,[2] as Code2 -- .... ,[3] etc
from
(
select codeid, code, ROW_NUMBER() over (partition by codeid order by id) rn
from yourtable
) p
pivot (max(code) for rn in ([1],[2])) p2 --, [3]... etc