Running total (COUNT) SQL Server - sql

I currently have this result
ID Code
1 AAA12
2 F5
3 GOFK568
4 G77
5 JLKJ4
6 FOG0
Now what i want to do is to create a third column that keeps a running total for codes that are above 4 in length.
Now, i have this code that gives me the sum of the code with above 4 in length.
SELECT * ,
SUM(CASE WHEN LENGTH(CODE) > 4 THEN 1 ELSE 0 END) AS [Count]
FROM Table1;
But this gives me this result
ID Code Count
1 AAA12 3
I am looking for a result like this
ID Code Running_Total
1 AAA12 1
2 F5 1
3 GOFK568 2
4 G77 2
5 JLKJ4 3
6 FOG0 3
I was working on something similar to this
SELECT * ,
CASE WHEN LENGTH(CODE) > 4 THEN (SUM(Code) OVER (PARTITION BY ID)) ELSE END
AS [Count]
FROM Table1;
But it still doesn't give me a running total.
I have an SQL Fiddle page
http://sqlfiddle.com/#!9/2746c/18
Any help would be great

Put the case in the sum:
SELECT Table1.* ,
SUM(case when len(Code) > 4 then 1 else 0 end) OVER (order BY ID) as counted
FROM Table1;

In Sql Server 2012+ you can use Sum() Over(Order by) function
SELECT Sum(CASE WHEN Len(code) > 4 THEN 1 ELSE 0 END)
OVER(ORDER BY id)
FROM Yourtable
for older versions
SELECT *
FROM Yourtable a
CROSS apply (SELECT Count(*)
FROM Yourtable b
WHERE a.ID >= b.ID
AND Len(code) > 4) cs (runn)
ANSI SQL method
SELECT ID,Code,
(SELECT count(*)
FROM Yourtable b
WHERE a.ID >= b.ID and char_length(code) > 4) AS runn
FROM Yourtable a

There are some good and efficient answers here.
But in case you want to try different approach then try following query:
SELECT
t1.*,
(Select sum(r.cnt) from
(SELECT COUNT(t2.code) as cnt FROM table1 AS t2
WHERE t2.Id <= t1.Id
group by t2.code
having len(t11.code) > 4) r
) AS Count
FROM table1 AS t1;
Here is the DEMO
Hope it helps!

Related

Find subsequent occurrence of a value in a table

I have a table which looks like shown below
ID SubmittedValue ApprovedValue
1 25.9 0
1 29 29
1 25.9 25.9
1 50 0
1 45 0
1 10 0
1 10 10
Expected result
ID SubsequentlyApproved(CNT) Total_Amt_sub_aprvd
1 2 35.9
We get the above result because 25.9+10 since it is repeated in the subsequent rows.
How to perform VLOOKUP like functionality for this scenario. I tried the subquery but it didn't work.
SELECT a.id,
SUM(CASE WHEN a.ApprovedValue=0 THEN 1 ELSE 0 END) AS SUB_COUNT
FROM myTable a
join (select id, sum( case when SubmittedValue=ApprovedValue then 1 end) as check_value from myTable) b
on b.id=a.id and SUB_COUNT=check_value
but this is not giving me the expected result.
You seem to want to count rows where the values are the same and the first value appears more than once. If so, you can use window functions and aggregation:
select id, count(*), sum(ApprovedValue)
from (select t.*, count(*) over (partition by id, SubmittedValue) as cnt
from t
) t
where cnt > 1 and SubmittedValue = ApprovedValue
group by id
Without window functions using a semi-join
select id, count(*), sum(submittedvalue)
from test t1
where submittedvalue=approvedvalue
and exists (select 1
from test t2
where t1.id=t2.id and t1.submittedvalue=t2.submittedvalue
group by id, submittedvalue
having count(*)>1)
group by id;

Calculation filtered sets in SQL

I have the following table invoving sort of 3 sets and I'm going to calculate the count of sets in whcich there is no (TaskId = 4), How can I achieve that?
SetId TaskId
1 0
1 1
1 4
2 0
2 2
2 3
3 0
3 2
3 4
Use conditional aggregation:
SELECT SetId
FROM yourTable
GROUP BY SetId
HAVING SUM(CASE WHEN TaskId = 4 THEN 1 ELSE 0 END) = 0;
The basic idea here is to scan each SetId group of records and count the number of times which a TaskId value of 4 occurs. The HAVING clause retains only groups for which the 4 value never occurs.
Use a CASE expression to check whether the TaskId value is 4. And use SUM function with grouping SetId.
Query
select [SetId],
SUM(case [TaskId] when 4 then 0 else 1 end) as [sum]
from [your_table_name]
group by [SetId];
I think you are looking for something like
SELECT *
FROM mytable t1
WHERE t1.SetId NOT IN (SELECT t2.SetId FROM mytable t2 WHERE t2.TaskId = 4)
(select the full sets that have no TaskId=4)
or
SELECT distinct SetId
FROM mytable t1
WHERE t1.SetId NOT IN (SELECT t2.SetId FROM mytable t2 WHERE t2.TaskId = 4)
(select just the SetIds that have no TaskId=4)

Cumulative distinct count filtered by last value - T-SQL

I am trying to come up with exactly the same answer as here:
Cumulative distinct count filtered by last value - DAX
but in SQL Server. For convenience I am copying the whole problem description.
I have a dataset:
month name flag
1 abc TRUE
2 xyz TRUE
3 abc TRUE
4 xyz TRUE
5 abc FALSE
6 abc TRUE
I want to calculate month-cumulative distinct count of 'name' filtered by last 'flag' value (TRUE). I.e. I want to have a result:
month count
1 1
2 2
3 2
4 2
5 1
6 2
In months 5 and 6 'abc' should be excluded because the flag switched to 'FALSE' in month 5.
I am thinking about using "over" clause with "partition by" but I don't have any experience here so it's a struggle for me.
UPDATE
I have updated the last row in exemplary source data.
was:
6 abc FALSE
is:
6 abc TRUE
And the last row in output data.
Was:
6 1
is:
6 2
It might have not been obivous from the description that it should work this way and the proposed answer does not solve this problem.
UPDATE 2
I have managed to create a query that gives the result but it's ugly and I think could be shrinked by using over clause. Can you help me with that?
select t5.month_current, count(*) as count from
(select t3.month month_current, t4.month months_until_current, t3.name, t4.flag from
(select name ,month from
(select distinct name
from Source_data) t1
,(select distinct month
from Source_data) t2) t3
left join
Source_data t4
on t3.name = t4.name and t3.month >= t4.month) t5
inner join
(select t3.month month_current, max(t4.month) real_max_month_until_current, t3.name from
(select name ,month from
(select distinct name
from Source_data) t1
,(select distinct month
from Source_data) t2) t3
left join
Source_data t4
on t3.name = t4.name and t3.month >= t4.month
group by
t3.month, t3.name) t6
on t5.month_current = t6.month_current
and t5.months_until_current = t6.real_max_month_until_current
and t5.name = t6.name
where t5.flag = 'TRUE'
group by t5.month_current
You can do a cumulative distinct count as:
select t.*,
sum(case when seqnum = 1 then 1 else 0 end) over (order by month) as cnt
from (select t.*,
row_number() over (partition by name order by month) as seqnum
from t
) t;
I don't understand the logic for incorporating the flag.
You can replicate the results in the question by incorporating the flag:
select t.*,
sum(case when seqnum = 1 and flag = 'true' then 1
when seqnum = 1 and flag = 'false' then -1
else 0
end) over (order by month) as cnt
from (select t.*,
row_number() over (partition by name, flag order by month) as seqnum
from t
) t;

SQL - categorize rows

Below is the result set I am working with. What I would like is an additional column that identifies a X number of rows as the same. In my result set, rows 1-4 are the same (would like to mark as 1), rows 5-9 are the same (mark as 2); row 10 (mark as 3)
How is this possible using just SQL? I can't seem to do this using rank or dense_rank functions.
ranking diff bool
-------------------- ----------- -----------
1 0 0
2 0 0
3 0 0
4 0 0
5 54 1
6 0 0
7 0 0
8 0 0
9 0 0
10 62 1
In general case you can do something like this:
select
t.ranking, t.[diff], t.[bool],
dense_rank() over(order by c.cnt) as rnk
from Table1 as t
outer apply (
select count(*) as cnt
from Table1 as t2
where t2.ranking <= t.ranking and t2.[bool] = 1
) as c
In your case you can do it even without dense_rank():
select
t.ranking, t.[diff], t.[bool],
c.cnt + 1 as rnk
from Table1 as t
outer apply (
select count(*) as cnt
from Table1 as t2
where t2.ranking <= t.ranking and t2.[bool] = 1
) as c;
Unfortunately, in SQL Server 2008 you cannot do running total with window function, in SQL Server 2012 it'd be possible to do it with sum([bool]) over(order by ranking).
If you have really big number of rows and your ranking column is unique/primary key, you can use recursive cte approach - like one in this answer, it's fastest one in SQL Server 2008 R2:
;with cte as
(
select t.ranking, t.[diff], t.[bool], t.[bool] as rnk
from Table1 as t
where t.ranking = 1
union all
select t.ranking, t.[diff], t.[bool], t.[bool] + c.rnk as rnk
from cte as c
inner join Table1 as t on t.ranking = c.ranking + 1
)
select t.ranking, t.[diff], t.[bool], 1 + t.rnk
from cte as t
option (maxrecursion 0)
sql fiddle demo

SQL Query for Count value from the latest date

I need to have a query that returns the ff:
Count from the latest Date in each Name
If the value of Count from the latest Date is -1 then it will return the count of the Date before the latest Date
If the value of Count from the latest Date is -1 and the other Date is -1. Then return 0
If the value of Count from the latest Date is -1 and no other Date of that Name. Then return 0
Example Table:
ID Name Date Count
1 Adj 09/29/2012 2
2 Adj 09/30/2012 4
3 Ped 09/29/2012 -1
4 Ped 09/30/2012 5
5 Mel 09/29/2012 3
6 Mel 09/30/2012 -1
7 Rod 09/30/2012 7
8 Ney 09/30/2012 -1
9 Jin 09/29/2012 -1
10 Jin 09/30/2012 -1
Desired Output:
Name Count
Adj 4
Ped 5
Mel 3
Rod 7
Ney 0
Jin 0
I am very confused on how to approach this in SQL since I only knew simple query.
Any idea on how to make a query for this? Thanks.
Btw, I'm sorry I forgot to include this. I am using SQL Server 2000.
Try this
SQL FIDDLE EXAMPLE
select A.name, isnull(T.[Count], 0) as [Count]
from (select distinct T.name from table1 as T) as A
outer apply
(
select top 1 T.[Count]
from table1 as T
where T.name = A.name and T.[Count] <> -1
order by T.[date] desc
) as T
order by A.name asc
UPDATE: for SQL 2000 you can use query like this
SQL FIDDLE EXAMPLE for SQL 2000
select A.name, isnull(T1.[Count], 0) as [Count]
from
(
select T.name, max(case when T.[Count] <> -1 then T.[date] else null end) as [date]
from table1 as T
group by T.name
) as A
left outer join table1 as T1 on T1.name = A.name and T1.[date] = A.[date]
but it relies on suggestion that you have unique constraint on name, [date] columns
an other one
Select * from
(
Select Test.name,[Count]
from TEST
Join(
Select name, MAX(Date) as Date from TEST
where [Count]<>-1
Group by Name) a
on a.Name=test.Name and a.Date=Test.Date
UNION
Select Distinct name,0 from test o where not Exists(Select * from test where name=o.Name and [count]<>-1)
) res
order by Name