I have two columns ID and FLAG as :
ID FLAG
1 Y
1 N
1 Y
1 N
1 N
1 N
1 N
1 Y
1 N
2 N
2 Y
2 N
2 N
2 Y
2 Y
2 N
Required Output:
ID FLAG REQ_COL
1 Y null
1 N 1
1 Y null
1 N 1
1 N 2
1 N 3
1 N 4
1 Y null
1 N 1
2 N null
2 Y null
2 N 1
2 N 2
2 Y null
2 Y null
2 N 1
Logic for required column :
For first occurence of ID , REQ_COL is null
If FLAG=Y then REQ_COL is null
IF previous value of FLAG is Y and there are consecutive N in FLAG , then the REQ_COL values are 1,2,3,4, 5.....
Else Null
I am trying to apply conditional row_number but not getting idea how to proceed.
Please help.
This might give you the result you are searching for...
Data Preparation
DECLARE #SOURCE_TABLE AS TABLE (realid int identity (1,1), ID int, FLAG CHAR(1))
INSERT INTO #SOURCE_TABLE (ID, FLAG)
VALUES (1, 'Y'),(1, 'N'),(1, 'Y'),(1, 'N'),(1, 'N'),(1, 'N'),
(1, 'N'),(1, 'Y'),(1, 'N'),(2, 'N'),(2, 'Y'),(2, 'N'),
(2, 'N'),(2, 'Y'),(2, 'Y'),(2, 'N')
Actual Select
SELECT ST2.ID, ST2.FLAG,
NULLIF(NULLIF (CHARINDEX('Y', REVERSE(
(
SELECT ST1.FLAG AS [text()]
FROM #SOURCE_TABLE ST1
WHERE ST1.ID = ST2.ID AND ST1.realid <= ST2.realid
ORDER BY ST1.realid
FOR XML PATH (''), TYPE
).value('text()[1]','VARCHAR(MAX)')
)), 1) - 1, -1) AS [REQ_COL]
FROM #SOURCE_TABLE AS ST2
ORDER BY ST2.realid
Related
I have the below table I want to find the Page number.
The logic is if the sum of both col A and col b is greater than or equal to 15 then it should be page and it should be incremented.
Col A will be always 1 or 0. Only Col B will changed
Problem :
Col X
Col y
col A
Col B
Pagenumber
x
y
1
105
x
y
1
0
x
y
1
2
x
y
1
6
x
y
1
3
null
y
0
1
x
y
1
2
x
y
1
3
x
y
1
1
x
y
1
4
Expected output :
Col X
Col y
col A
Col B
Pagenumber
x
y
1
105
Page 1
x
y
1
0
Page 2
x
y
1
2
Page 2
x
y
1
6
Page 2
x
y
1
3
Page 2
null
y
0
1
Page 3
x
y
1
2
Page 3
x
y
1
3
Page 3
x
y
1
1
Page 3
x
y
1
4
Page 3
Query without pagenumber column:
SELECT
IIF(c2.isdeleted = 1 OR c2.approved = 0, NULL, c2.content) AS Content,
(SELECT STRING_AGG(c1.content, ', ')
FROM comments c1
WHERE c1.parentcommentid = c2.id
AND c1.isdeleted = 0
AND c1.approved = 1) ChildContent,
IIF(c2.isdeleted = 1 OR c2.approved = 0, 0, 1) AS Contentcount,
(SELECT COUNT(c1.content)
FROM comments c1
WHERE c1.parentcommentid = c2.id
AND c1.isdeleted = 0
AND c1.approved = 1) ChildContentcount
FROM
comments c2
WHERE
c2.discussionid = '402930'
AND c2.parentcommentid IS NULL
-- AND Content IS NOT NULL
ORDER BY
c2.pinned DESC,
c2.createddate
You need to specify the order of rows in which the cumulative sum should be calculated.
You can use a recursive CTE to calculate and partition the running sum.
with t(rn, x, y, a, b) as (
select row_number() over (order by ???), -- set the ordering columns here
x, y, a, b
from your_table
),
cte(rn, x, y, a, b, running_sum, page) as (
select t.rn, t.x, t.y, t.a, t.b, t.a + t.b, 1
from t where rn = 1
union all
select t.rn, t.x, t.y, t.a, t.b,
t.a + t.b + case when cte.running_sum >= 15 then 0 else cte.running_sum end,
case when cte.running_sum >= 15 then cte.page + 1 else cte.page end
from cte join t on t.rn = cte.rn + 1
where t.rn > 1
)
select *
from cte;
Result:
I have a log file I need to either rank (but treating sequential and equal rows as ties), or merge sequential equal rows (based on specific column). My table looks like below, The Start and Stop are all being sequential (within the same ID window)
ID Start Stop Value
1 0 1 A
1 1 2 A
1 2 3 A
1 3 4 B
1 4 5 B
1 5 6 A
2 3 4 A
I have two approches to get what I need.
Approach 1: Rank (treating sequential rows with equal values in "Value" as ties) and using ID as partition.
This should give the output below. But how do I do the special rank: Treating sequential rows with equal values in "Value" as ties.
Select *,
rank() OVER (partition by id order by start, stop) as Rank,
XXX as SpecialRank
from Table
ID Start Stop Value Rank SpecialRank
1 0 1 A 1 1
1 1 2 A 2 1
1 2 3 A 3 1
1 3 4 B 4 2
1 4 5 B 5 2
1 5 6 A 6 3
2 3 4 A 1 1
Approach 2: Merge sequential rows with equal values in "Value".
This will shall create a table like below.
ID Start Stop Value
1 0 3 A
1 3 5 B
1 5 6 A
2 3 4 A
I don't know if this helps, but I have also a nextValue column that might help in this
ID Start Stop Value NextValue
1 0 1 A A
1 1 2 A A
1 2 3 A B
1 3 4 B B
1 4 5 B A
1 5 6 A A
2 3 4 A ...
Example-table:
CREATE TABLE #Table ( id int, start int, stop int, Value char(1), NextValue char(1));
INSERT INTO #Table values (1,0, 1, 'A', 'A');
INSERT INTO #Table values (1,1, 2, 'A', 'A');
INSERT INTO #Table values (1,2, 3, 'A', 'B');
INSERT INTO #Table values (1,3, 4, 'B', 'B');
INSERT INTO #Table values (1,4, 5, 'B', 'A');
INSERT INTO #Table values (1,5, 6, 'A', 'A');
INSERT INTO #Table values (2,3, 4, 'A', null);
Use a self join to an aggregate subquery from the full set, e.g.
with rankTable (id, value) as
( select 1, 'A' union all select 1, 'A' union all select 1, 'B' union all select 2, 'A')
select t2.* from rankTable t1 join (
select id, value, rank() over (partition by id order by value) as specialRank from
(
select distinct id, value
from rankTable
) t) t2 on t2.id =t1.id and t2.value = t1.value
id value specialRank
1 A 1
1 A 1
1 B 2
2 A 1
I'm trying to write a query on the below data set to add a new column which has some sort of "period_id_group".
contiguous new_period row_nr new_period_starting_id
0 0 1 0
1 1 2 2
1 0 3 0
1 0 4 0
1 1 5 5
1 0 6 0
What I'm trying to get is:
contiguous new_period row_nr new_period_starting_id period_id_group
0 0 1 0 0
1 1 2 2 2
1 0 3 0 2
1 0 4 0 2
1 1 5 5 5
1 0 6 0 5
The logic is that for each 0 value in the new_period_starting_id, it has to get the >0 value from the row above.
So, for row_nr = 1 since there is no row before it, period_id_group is 0.
For row_nr = 2 since this is a new perid (marked by new_period = 1), the period_id_group is 2 (the id of this row).
For row_nr = 3 since it's part of a contiguous range (because contiguous = 1), but is not the start of the range, because it's not a new_period (new_period = 0), its period_id_group should inherit the value from the previous row (which is the start of the contiguous range) - in this case period_id_group = 2 also.
I've tried multiple versions but couldn't get a good solution for SQL Server 2008R2, since I can't use LAG().
What I have, so far, is a shameful:
select *
from #temp2 t1
left join (select distinct new_period_starting_id from #temp2) t2
on t1.new_period_starting_id >= t2.new_period_starting_id
where 1 = case
when contiguous = 0
then 1
when contiguous = 1 and t2.new_period_starting_id > 0
then 1
else 1
end
order by t1.rn
Sample data script:
declare #tmp2 table (contiguous int
, new_period int
, row_nr int
, new_period_starting_id int);
insert into #tmp2 values (0, 0, 1, 0)
, (1, 1, 2, 2)
, (1, 0, 3, 0)
, (1, 0, 4, 0)
, (1, 1, 5, 5)
, (1, 0, 6, 0);
Any help is appreciated.
So, if I'm understanding you correctly, you just need one additional column.
SELECT t1.contiguous, t1.new_period, t1.row_nr, t1.new_period_starting_id,
(SELECT TOP 1 (new_period_starting_id)
FROM YourTable t2
WHERE t2.row_nr <= t1.row_nr
AND t2.period_id_group > 0 /* optimization */
ORDER BY t2.row_nr DESC /* optimization */) AS period_id_group
FROM YourTable t1
Here is yet another option for this.
select t1.contiguous
, t1.new_period
, t1.row_nr
, t1.new_period_starting_id
, x.new_period_starting_id
from #tmp2 t1
outer apply
(
select top 1 *
from #tmp2 t2
where (t2.row_nr = 1
or t2.new_period_starting_id > 0)
and t1.row_nr >= t2.row_nr
order by t2.row_nr desc
) x
Found the solution:
select *
, case
when contiguous = 0
then f1
when contiguous = 1 and new_periods = 1
then f1
when contiguous = 1 and new_periods = 0
then v
else NULL
end [period_group]
from (
select *
, (select max(f1) from #temp2 where new_period_starting_id > 0 and rn < t1.rn) [v]
from #temp2 t1
) rs
order by rn
I have a table with following sampled rows:
Id CompanyId value
1 X a
2 X b
3 X c
4 X d
5 Y e
6 Y f
7 z g
8 Z h
9 X i
10 X j
I want to have a view with following result :
Id CompanyId ParentId
1 X NULL
2 X NULL
3 X NULL
4 X NULL
5 Y 1
6 Y 1
7 z 5
8 Z 5
9 X 7
10 X 7
On this result calculated ParentId for each row. ParentId for each row equal to Id of first row from previous companyId.
I hope that SQL Server 2012 tag is here for reason :)
;with x as (
select *, lag(companyid) over(order by id) as prev
from #t1
),
y as (
select *, sum(case when prev = companyid then 0 else 1 end) over(order by id) as grp
from x
)
select y.id, y.companyid, min(y1.id)
from y
left join y y1 on y1.grp = y.grp-1
group by y.id, y.companyid
A B
1 2
1 1
1 3
1 4
3 3
3 4
4 5
How can one use T-SQL to select only those rows that have column B value not greater than the next greater values in column A?
For example, if above table is the input, the output should be as follows;
A B
1 2
1 1
3 3
4 5
select t1.A, t1.B
from tbl t1
where t1.B < isnull((select min(t2.A)
from tbl t2
where t2.A > t1.A), t1.B+1)