How to count an occurance of a specific value in each partition? - tsql

I need to count the occurance of -1 value for every partition of a table. If a partition contains only two rows I could use min,max functions but for partitions with more than two rows it's not a solution.
CREATE TABLE #Data(ID int,name_of_institution varchar(200),wasko_id int)
INSERT INTO #Data(ID,name_of_institution,wasko_id)
SELECT 4822,'Bailiff xxx',-1 union all
SELECT 4820,'Bailiff xxx',-1 union all
SELECT 4819,'Bailiff xxx',2332 union all
SELECT 4700,'Bailiff yyy',-1 union all
SELECT 4701,'Bailiff yyy',222
select DENSE_RANK() over (order by name_of_institution) as DR,* from #Data
I expect the output of 2 for 'Bailiff xxx' partition and 1 for 'Bailiff yyy' partition.

Use an excel like sumif: Sum of a conditional insert, where on True you sum 1 and on False you sum 0: iif(condition, 1, 0)
select name_of_institution, sum(iif(wasko_id = -1, 1, 0)) as DR
from #Data
group by name_of_institution

Related

How to use WHERE with virtual column name added with UNION?

SELECT '1000000' AS number
UNION ALL
SELECT '541' AS number
UNION ALL
SELECT '-500' AS number
UNION ALL
SELECT '100' AS number
UNION ALL
SELECT number, 'biggest' AS result
WHERE number = 1000000
How to make this work? My task is to find the biggest number from those that I added.
SELECT '1000000' AS number
UNION ALL
SELECT '541' AS number
UNION ALL
SELECT '-500' AS number
UNION ALL
SELECT '100' AS number
UNION ALL
SELECT number, 'biggest' AS result
WHERE number = 1000000
How to make this work? My task is to find the biggest number from those that I added.
You need to wrap the query in a derived table to be able access a column alias
select *
from (
SELECT 1000000 AS number
UNION ALL
SELECT 541 AS number
UNION ALL
SELECT -500 AS number
UNION ALL
SELECT 100 AS number
)
WHERE number = 1000000
But to find the highest number, you can use an order by and limit:
select *
from (
SELECT 1000000 AS number
UNION ALL
SELECT 541 AS number
UNION ALL
SELECT -500 AS number
UNION ALL
SELECT 100 AS number
)
order by number desc
limit 1
Alternatively you can also simplify this by using a VALUES clause:
select *
from (
values (1000000),(541),(-500),(100)
) as t(number)
order by number desc
limit 1
you can use common table expresssion with FETCH as given below:
WITH CTE_Number AS (
SELECT 1000000 AS number
UNION ALL
SELECT 541 AS number
UNION ALL
SELECT -500 AS number
UNION ALL
SELECT 100 AS number
)
SELECT Number,'Biggest' as result
FROM CTE_Number
ORDER BY Number DESC
FETCH FIRST ROW ONLY;

Break array_agg column into batches

I have a query like the following:
SELECT mt.group_id, array_agg(mt.id) as my_array
FROM myTable mt
GROUP BY mt.group_id;
In some contexts the array contains too many elements and a max byte limit error is thrown.
Is there any way that I can break the array into separate smaller batches per row? So for example, if I wanted a maximum batch size of 2 the result set might look like:
group_id, my_array
1, {1,2}
1, {3,4}
2, {5}
You can use a window function to add a subgroup column, then group by that column in addition to the existing group_id.
Due to restrictions on where window functions can be used, this requires a nested select to add the subgroup at one level and group by it at a higher level.
with mytable as (select * from (values (1,1),(1,2),(1,3),(1,4),(2,5)) f(group_id,id))
SELECT group_id, array_agg(mt.id) as my_array from
(select *,(row_number() over (partition by group_id)-1)/2 as subgroup FROM myTable) mt
GROUP BY mt.group_id, subgroup order by group_id, subgroup;

How to list double entries of the concatenation of two columns?

How to list the double entries of the concatenation of two columns ?
Currently, I'm using this query to list doubles in a single column:
SELECT
COUNT(col_a) AS count,
col_a
FROM mytable
GROUP BY col_a
HAVING COUNT(col_a) > 1
ORDER BY count DESC
demo:db<>fiddle
First concatenate them and do your operation afterwards:
SELECT
COUNT(concat) AS count,
concat
FROM (
SELECT col_a || col_b AS concat FROM t
) s
GROUP BY concat
HAVING COUNT(concat) > 1
ORDER BY count DESC

Querying duplicate values and selecting column values acording to them

I need to extract the numbers from the table TEST which has more than two area types and has the area ="three" as a value. I should get the results "b" and "f".
Thank you.
Below are the queries -
select count(*), number from <tableName> where number in (select number from <tableName> where area='three') group by number having count(*)>1;
select number from <tableName> group by number having count(*)>1 and sum(case when area='Three' then 1 else 0) = 1;

How to match records for two different groups?

I have one main table called Event_log which contains all of the records that I need for this query. Within this table there is one column that I'm calling "Grp". To simplify things, assume that there are only two possible values for this Grp: A and B. So now we have one table, Event_log, with one column "Grp" and one more column called "Actual Date". Lastly I want to add one more Flag column to this table, which works as follows.
First, I order all of the records in descending order by date as demonstrated below. Then, I want to flag each Group "A" row with a 1 or a 0. For all "A" rows, if the previous record (earlier in date) = "B" row then I want to flag 1. Otherwise flag a 0. So this initial table looks like this before setting this flag:
Actual Date Grp Flag
1-29-13 A
12-27-12 B
12-26-12 B
12-23-12 A
12-22-12 A
But after these calculations are done, it should look like this:
Actual Date Grp Flag
1-29-13 A 1
12-27-12 B NULL
12-26-12 B NULL
12-23-12 A 0
12-22-12 A 0
How can I do this? This is simpler to describe than it is to query!
You can use something like:
select el.ActualDate
, el.Grp
, Flag = case
when el.grp = 'B' then null
when prev.grp = 'B' then 1
else 0
end
from Event_log el
outer apply
(
select top 1 prev.grp
from Event_log prev
where el.ActualDate > prev.ActualDate
order by prev.ActualDate desc
) prev
order by el.ActualDate desc
SQL Fiddle with demo.
Try this
;with cte as
(
SELECT CAST('01-29-13' As DateTime) ActualDate,'A' Grp
UNION ALL SELECT '12-27-12','B'
UNION ALL SELECT '12-26-12','B'
UNION ALL SELECT '12-23-12','A'
UNION ALL SELECT '12-22-12','A'
)
, CTE2 as
(
SELECT *, ROW_NUMBER() OVER (order by actualdate desc) rn
FROM cte
)
SELECT a.*,
case
when A.Grp = 'A' THEN
CASE WHEN b.Grp = 'B' THEN 1 ELSE 0 END
ELSE NULL
END Flag
from cte2 a
LEFT OUTER JOIN CTE2 b on a.rn + 1 = b.rn