I have a TABLE with STR DNA DATA the following Table [DYS]
Id
DYS385
3
10-19
4
13-16
5
13-18
6
13-19
7
13-17
8
13-18
9
13-18
10
14-19
11
13-19
12
13-18
I am USING the following script to split the values of [DYS385]
select top 10 id,[DYS385],t.Value
from dys
OUTER APPLY(select * from string_split([DYS385],'-')) t
where dys385 is not null
Output
Id
DYS385
VALUE
3
10-19
10
3
10-19
19
4
13-16
13
4
13-16
16
5
13-18
13
5
13-18
18
6
13-19
13
6
13-19
19
7
13-17
13
7
13-17
17
I want to get for each Value, the Rank
example
10-19 => 10: Rank 1, 19: Rank 2
Desired results:
Id
DYS385
VALUE
RANK
3
10-19
10
1
3
10-19
19
2
4
13-16
13
1
4
13-16
16
2
5
13-18
13
1
5
13-18
18
2
6
13-19
13
1
6
13-19
19
2
7
13-17
13
1
7
13-17
17
2
Use an alternative string-split method, such as XML or Json that can return an ordinal position, such as:
create function dbo.SplitString(#string varchar(1000), #Delimiter varchar(10))
returns table
as
return(
select j.[value], 1 + Convert(tinyint,j.[key]) Seq
from OpenJson(Concat('["',replace(#string,#delimiter, '","'),'"]')) j
);
select value, Seq as [Rank]
from dbo.SplitString('10-19','-')
order by [Rank];
Example fiddle
Given this data:
CREATE TABLE dbo.Something(Id int, DYS385 varchar(10));
INSERT dbo.Something(Id, DYS385) VALUES (3 , '10-19'),
(4 , '13-16'), (5 , '13-18'), (6 , '13-19'),
(7 , '13-17'), (8 , '13-18'), (9 , '13-18'),
(10, '14-19'), (11, '13-19'), (12, '13-18');
Another way to make sure you rank the broken-up strings in the right order could be to use tricks like PARSENAME(), though this can be sensitive to strings lengths and whether a dot is valid within the data:
SELECT s.Id, s.DYS385, value = v.v, [rank] = ROW_NUMBER() OVER
(PARTITION BY s.Id ORDER BY c.c DESC)
FROM dbo.Something AS s
CROSS APPLY (VALUES(1),(2)) AS c(c)
CROSS APPLY (VALUES(PARSENAME(REPLACE(s.DYS385,'-','.'),c.c))) AS v(v)
ORDER BY s.Id, [rank];
Output:
Id
DYS385
value
rank
3
10-19
10
1
3
10-19
19
2
4
13-16
13
1
4
13-16
16
2
5
13-18
13
1
5
13-18
18
2
6
13-19
13
1
6
13-19
19
2
7
13-17
13
1
7
13-17
17
2
8
13-18
13
1
8
13-18
18
2
9
13-18
13
1
9
13-18
18
2
10
14-19
14
1
10
14-19
19
2
11
13-19
13
1
11
13-19
19
2
12
13-18
13
1
12
13-18
18
2
Example db<>fiddle
Split_string has an option to output this rank, called ordinal. Just add an extra parameter with the value of 1:
SELECT *FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ', 1);
That returns:
value ordinal
Lorem 1
ipsum 2
dolor 3
sit 4
amet. 5
In your case the query would be:
select top 10 id,[DYS385],t.* from dys OUTER APPLY(select * from string_split([DYS385],'-',1)) t where dys385 is not null
We can also make recursive split_string function which returns the rank of each item as follows
Link dbfiddle
Create function Split_Recursive(#string nvarchar(max),#delimiter as varchar(1)) returns Table
as
return(
with cte as(
select 1 N,
case when charindex(#delimiter,#string,1) =0 then #string else
substring(#string,1,-1+charindex(#delimiter,#string,1)) end [Found],
case when charindex(#delimiter,#string,1)=0 then #string else substring(#string,1+charindex(#delimiter,#string,1) ,len(#string))
end [MYSTRING]
union all
select 1+n,
case when charindex(#delimiter,[MYSTRING],1)=0 then [MYSTRING] else
substring([MYSTRING],1,-1+charindex(#delimiter,[MYSTRING],1)) end,substring([MYSTRING],1+charindex(#delimiter,[MYSTRING]),len([MYSTRING])) from cte
where charindex(#delimiter,[MYSTRING],1)>0),
cte2 as (select N,Found from cte
union select 1+t.N,Mystring from cte OUTER APPLY(select top 1 N from cte order by n desc)t where t.n=cte.n
)
select N Rank,Found from cte2
)
go
select * from dbo.Split_Recursive('12-16','-')
Output
Rank
Found
1
12
2
16
Here is my problem: I have a list of flagged values, I want to see where those values would be in the case they weren't flagged. But I don't want the other flagged values to influence the order.
Note: Flagged values are the ones with CurrentPlace 10000
ID Value CurrentPlace
------------------------
1 2 1
2 8 3
3 3 2
4 4 10000
5 5 10000
6 10 10000
Using:
select *
from
(select
id, value,
rank() over (order by Value asc) as Rank
from
tbl1) r
where
r.ID in (select id from tbl1 where CurrentPlace = 10000)
Desired output:
ID Value Rank
------------------
4 4 3
5 5 3
6 10 4
But I'm getting this instead:
ID Value Rank
------------------
4 4 3
5 5 4
6 10 6
Any help will be appreciated
Thank you guys
I've solved with
SELECT ID, Value, Rank
FROM tbl1 a
CROSS APPLY
(SELECT isnull(max(currentPlace),0) + 1 AS Rank FROM tbl1 WHERE value < a.value and currentPlace <> 10000) b
WHERE a.CurrentPlace = 10000
Please feel free to comment this out.
I have a query named "QueryTotalGrades" which has three fields (Group, StudentID and Mark). each studentID has more than one mark. What I want to do is to create another query that conduct the following :
1- Sum mark for each studentID as a sumOfMark (Descending order)
2- Display the top 2 of sumOfMarks per group.
Example: let say that the "QueryTotalGrades" has the following values.
I'm using Microsoft access 2013
Group StudentID Mark
1 1 8
1 1 7
1 1 8
1 2 7
1 2 7
1 2 7
1 3 9
1 3 9
1 3 9
2 4 5
2 4 7
2 4 5
2 5 7
2 5 7
2 5 7
2 6 6
2 6 6
2 6 6
3 7 8
3 7 7
3 7 8
3 8 7
3 8 7
3 8 7
3 9 10
3 9 10
3 9 10
,so the output that I want should be as following
Group StudentID SumOfMark
1 3 27
1 1 23
2 5 21
2 6 18
3 9 30
3 7 23
I have tried many solutions, but no avail. HELP
A little longwinded but:
select
t1.[Group], t1.StudentID, t1.SumOfMark
from
(select [Group], StudentID, sum(Mark) as SumOfMark
from QueryTotalGrades
group by [Group], StudentID) as t1
where
(select count(*) from
(select [Group], StudentID, sum(Mark) as SumOfMark
from QueryTotalGrades
group by [Group], StudentID) as t2
where
t2.[Group] = t1.[Group] and
t2.SumOfMark >= t1.SumOfMark) <= 2
order by
t1.[Group], t1.SumOfMark desc
You can play with it here: SQL Fiddle
Query
;with cte as
(
select rn=row_number() over
(
partition by [Group]
order by sum(Mark) desc
),
[Group],StudentID,
sum(Mark) as SumOfMark
from student
group by [Group],StudentID
)
select [Group],StudentId,SumOfMark from cte where rn in (1,2);
fiddle demo
In SQL Server 2008 R2, I have a table like this:
ID Dates Count
1 03-02-2014 2
2 04-02-2014 1
3 05-02-2014 NULL
4 06-02-2014 1
5 07-02-2014 3
6 08-02-2014 NULL
7 09-02-2014 2
8 10-02-2014 NULL
9 11-02-2014 1
10 12-02-2014 3
11 13-02-2014 NULL
12 14-02-2014 1
I have an INT variable having some value such as #XCount = 15.
My requirement is to update the count column with (#XCount - Count) such as the result of previous record will be subtracted by the Count value in the next record.
Result:
ID Dates Count
1 03-02-2014 13 (15-2)
2 04-02-2014 12 (13-1)
3 05-02-2014 12 (12-0)
4 06-02-2014 11 (12-1)
5 07-02-2014 8 (11-3)
6 08-02-2014 8 (8-0)
7 09-02-2014 6 (8-2)
8 10-02-2014 6 (6-0)
9 11-02-2014 5 (6-1)
10 12-02-2014 2 (5-3)
11 13-02-2014 2 (2-0)
12 14-02-2014 1 (2-1)
I'm reluctant to use cursors as a solution. Can somebody help me?
How about something like
DECLARE #XCount INT = 15
;WITH Vals AS(
SELECT ID, Dates, [Count] OriginalCount, #XCount - ISNULL([COUNT],0) NewCount
FROM Table1
WHERE ID = 1
UNION ALL
SELECT t.ID, t.Dates, t.[Count], v.NewCount - ISNULL(t.[Count],0)
FROM Table1 t INNER JOIN Vals v ON t.ID = v.ID + 1
)
SELECT *
FROM Vals
SQL Fiddle DEMO
Do note thought that this is a recursive query, and that sometimes (until the tech allows for it, such as SQL SERVER 2012 LAG or Running totals) old does work.
The following is how I have created the table:
CREATE TABLE #tmp
(
[Counter] int
,Per date not null
,Cam float
,CamMeg float
,Hfx float
,HfxMet float
,TorMetric float
)
The following is how I call the table later on in my script:
SELECT
((ROW_NUMBER() over(order by Per desc)-1)/#Avg)+1 as [Counter], Per,
Cam,
AVG(CamMetric) as CamMet,
HfxMe,
FROM #tmp
GROUP BY [counter] ;
DROP TABLE #tmp
The following are the errors that I get:
Msg 8120, Level 16, State 1, Line 175
Column '#tmp.Per' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8120, Level 16, State 1, Line 175
Column '#tmp.Per' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
What am I doing incorrectly?
The data looks like the following
counter --- per ---Cam --- HfxMet ---......
1 2012-02-09 3 16
1 2012-02-24 4 12
1 2012-03-04 2 15
2 2012-03-15 1 18
2 2012-03-30 6 20
2 2012-04-07 10 6
3 2012-04-28 8 3
Now I want to add two more columns called CamMetricAvg and HfxMetric that will look at all counters that are 1 and then get the CamMetric and HfxMetric values respectively and give the average and put that on each Like the following:
counter --- per ---Cam --- CamMt ---
1 2012-02-09 3 3
1 2012-02-24 4 3
1 2012-03-04 2 3
2 2012-03-15 1 5.6
2 2012-03-30 6 5.6
2 2012-04-07 10 5.6
3 2012-04-28 8 8
SELECT [Counter], Period,
CamMetric,
AvgCamMetric = AVG(CamMetric) OVER(PARTITION BY Counter),
HfxMetric,
AvgHfxMetric = AVG(HfxMetric) OVER(PARTITION BY Counter)
... repeat for other metrics ...
FROM #tmpTransHrsData
GROUP BY [Counter], Period, CamMetric, HfxMetric;
SQLFiddle example