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
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
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
I have a table in SQL Server with two fields.
Total Group
35645 24
12400 55
30000 41
I want to split each group into smaller segments of fixed size 7000, with the remainder of each group into the last segment. So, the output should look like below.
Segment Total Group
1 7000 24
2 7000 24
3 7000 24
4 7000 24
5 7000 24
6 645 24
1 7000 55
2 5400 55
1 7000 41
2 7000 41
3 7000 41
4 7000 41
5 2000 41
This should do it:
declare #t table (Total int,[Group] int)
insert into #t(Total,[Group]) values
(35645,24 ),
(12400,55 ),
(30000,41 )
;With Numbers as (
select ROW_NUMBER() OVER (ORDER BY number)-1 n
from master..spt_values
)
select
n.n+1 as Segment,
CASE WHEN (n.n+1)*7000 < t.Total THEN 7000
ELSE t.Total - (n.n*7000) END as Total,
t.[Group]
from
#t t inner join
Numbers n on n.n*7000 < t.Total
(If you already have a Numbers table you can eliminate that part. I'm using spt_values just as a table that I know has plenty of rows in it, so that the ROW_NUMBER() expression should generate all of the necessary numbers)
Results:
Segment Total Group
-------------------- -------------------- -----------
1 7000 24
2 7000 24
3 7000 24
4 7000 24
5 7000 24
6 645 24
1 7000 55
2 5400 55
1 7000 41
2 7000 41
3 7000 41
4 7000 41
5 2000 41
I prepared following SELECT statement using SQL CTE expression and SQL numbers table function
declare #divisor int = 7000
;with CTE as (
select
Total,
[Group],
#divisor divisor,
(Total / #divisor) quotient,
(Total % #divisor) reminder
from t
), NT as (
SELECT i FROM dbo.NumbersTable(1, (select max(quotient) from CTE) ,1)
)
select
case when i = 0 then reminder else divisor end as Total,
[Group]
from (
select *
from CTE, NT
where quotient >= i
union all
select *, 0 as i
from CTE
where reminder >= 0
) t
order by [Group], i desc
SELECT name,
batchno,
recievedeggs,
settingqnty,
CONVERT(VARCHAR(50), settingdate, 103) AS settingdate,
setteroutput,
( 100 * setteroutput / settingqnty ) AS [SetterHatch%],
hathersettingqty,
hatcheroutput,
culls,
[hatcherhatch%],
( 100 * hatcheroutput / Sum(settingqnty) ) AS [Hatch%],
CONVERT(VARCHAR(50), pulloutdate, 103) AS pulloutdate,
hatcher
FROM (SELECT SH.name,
MS.batchno,
MS.recievedeggs,
MS.quantity AS SettingQnty,
MS.settingdate,
SD.remainingqnty AS SetterOutput,
MH.settingqntity AS HatherSettingQty,
MH.saleablechicks AS HatcherOutput,
MH.culls,
Round(MH.hatchpercent, 2) AS [HatcherHatch%],
MH.pulloutdate,
SH1.name AS Hatcher
FROM k_hm_settergetterallocationdet MS
INNER JOIN k_hm_setterdetails SD
ON MS.sno = SD.id
INNER JOIN k_hm_hatcherdetails HD
ON SD.sno = HD.id
INNER JOIN k_hm_masterhatcherdet MH
ON HD.sno = MH.id
INNER JOIN k_hm_gettersetterdet SH
ON MS.name = SH.sno
INNER JOIN k_hm_gettersetterdet SH1
ON HD.hatchername = SH1.sno
WHERE settingdate BETWEEN #fromdate AND #todate)a
GROUP BY a.settingdate,
a.name,
a.recievedeggs,
a.settingdate,
a.setteroutput,
a.hathersettingqty,
a.hatcheroutput
ORDER BY a.settingdate DESC
using this am getting output like:
S.No. SetterName SettingDate FlockNo Rec.Eggs SettingEggs SetterO/P Setter% HatcherName HatcherQnty PulloutDate HatcherO/P Culls Hatcher% Total Hatch%
1 Setter1 01/06/2014 Batch10 2500 2150 2136 99 Hatcher1 2136 22/06/2014 2115 15 99.02 98
2 Setter1 01/06/2014 Batch10 2500 2355 2341 99 Hatcher1 2341 22/06/2014 2314 21 98.85 98
3 Setter2 01/06/2014 Batch10 2450 2255 2241 99 Hatcher1 2241 22/06/2014 2221 20 99.11 98
but I want output like this:
S.No. SetterName SettingDate FlockNo Rec.Eggs SettingEggs SetterO/P Setter% HatcherName HatcherQnty PulloutDate HatcherO/P Culls Hatcher% Total Hatch%
1 Setter1,Setter3 01/06/2014 Batch10 7450 6760 6781 99 Hatcher1 6781 22/06/2014 6650 15 99.02 98
I have tried in this way but it's not correct.
DECLARE #t VARCHAR(Max)
Select #t = ISNULL(#t + ',' + SetterName, SetterName) from hk
where FlockNo in (select FlockNo from hk)
(select #t as setterName,SettingDate,FlockNo,sum(rec) as rec,SUM(SettingEggs)as se,sum([SetterO/P])assop,([Setter%])asse,HatcherName,
Sum(HatcherQnty)HQ,PulloutDate,sum([HatcherO/P]) as hatchero,min(Culls)as culls,max([Hatcher%])as hat,
(Total)
from hk
group by FlockNo,[Setter%],SettingDate,HatcherName,PulloutDate,Total,FlockNo)
getting result
Setter1,Setter2,Setter3 2014-01-06 Batch10 7450 6760 6718 99 Hatcher1 6718 2014-06-22 6650 15 99 98
I have this query that returns Quantity based discount list
with cte([item code],price,discount,rngLow,rngHigh,id) as
(
select 'xxx-xxxxxxx' as [item code],l.t$pric,l.t$disc,lqanp=l.t$qanp,hqanp=h.t$qanp,id = row_number() over(partition by h.t$qanp order by h.t$qanp) from EdiCatalog l
join ediCatalog h on l.comno=h.comno and l.t$cpls=h.t$cpls and l.t$cuno=h.t$cuno and h.t$item=l.t$item and l.t$qanp < h.t$qanp
where l.comno=#comno and l.t$cpls=#cpls and l.t$cuno=#cuno
)
select * from cte
returning result set
How do I transform the result set to this
You can start with this:
SELECT *
FROM cte a
WHERE rngHigh=(
SELECT MIN(rngHigh)
FROM cte b
WHERE b.rngLow=a.rngLow
)
Which will give you this result set:
discount rngLow rngHigh
40 1 9
68 9 23
73 23 47
75 47 299
#Frazz,
Here is what I have now
with little alteration to what you suggested..
SELECT rngLow=case rngLow
when 1 then rnglow
else rnglow+1 end,rngHigh,discount,id
FROM cte a
WHERE rngHigh=(
SELECT MIN(rngHigh)
FROM cte b
WHERE b.rngLow=a.rngLow
)