Why after group by 0 becomes null? - sql

I have the function:
CREATE FUNCTION fnc_successful_checks_blocks(block1 varchar, block2 varchar)
RETURNS TABLE(Started_block1 BIGINT, Started_block2 BIGINT, Started_both BIGINT, Started_no_one BIGINT)
AS $$
DECLARE
count_peers BIGINT := (SELECT COUNT(peers.nickname)
FROM peers);
BEGIN
RETURN QUERY
WITH startedblock1 AS (SELECT DISTINCT peer
FROM Checks
WHERE Checks.task SIMILAR TO concat(block1,'[0-9]_%')),
startedblock2 AS (SELECT DISTINCT peer
FROM Checks
WHERE Checks.task SIMILAR TO concat(block2,'[0-9]_%')),
startedboth AS (SELECT DISTINCT startedblock1.peer
FROM startedblock1 INNER JOIN startedblock2 ON startedblock1.peer = startedblock2.peer),
startedoneof AS(SELECT DISTINCT peer
FROM ((SELECT * FROM startedblock1) UNION (SELECT * FROM startedblock2)) AS foo)
SELECT (SELECT COUNT(*) * 100/count_peers
FROM startedblock1) AS Started_block1,
(SELECT COUNT(*) * 100/count_peers
FROM startedblock2) AS Started_block2,
(SELECT COUNT(*) * 100/count_peers
FROM startedboth) AS Started_both,
(SELECT (count_peers - COUNT(*)) * 100/count_peers
FROM startedoneof) AS Started_no_one;
END
$$
LANGUAGE plpgsql;
The problem is that in the last query and its subqueries there is a need to add a group by.
SELECT (SELECT COUNT(*) * 100/count_peers
FROM startedblock1
GROUP BY count_peers) AS Started_block1,
(SELECT COUNT(*) * 100/count_peers
FROM startedblock2
GROUP BY count_peers) AS Started_block2,
(SELECT COUNT(*) * 100/count_peers
FROM startedboth
GROUP BY count_peers) AS Started_both,
(SELECT (count_peers - COUNT(*)) * 100/count_peers
FROM startedoneof
GROUP BY count_peers) AS Started_no_one;
But after that, in the table that the function returns, the zeros became null. What could be the problem?
Sample output before group by:
Cstarted_block1
started_block2
started_both
started_no_one
75
0
0
25
Sample output after group by:
Cstarted_block1
started_block2
started_both
started_no_one
75
null
null
25
I tried to use the COALESCE function but it didn't help. I tried to put 100/count_peers into the aggregate function. I tried type conversion.

Related

How to divide the count() of two seperate queries in DB2

So I have
select count(*) from ( "query1")
select count(*) from ( "query2")
I want to divide the two and get the floating point result.
I was told to use something like this
SELECT (COUNT(smtg) * 1.0) / COUNT(smtg)
But Im not sure
You can just do:
select q1.cnt * 1.0 / q2.cnt
from (select count(*) as cnt from ( "query1") ) q1 cross join
(select count(*) as cnt from ( "query2") ) q2;
Or, if you prefer:
select ( (select count(*) from ( "query1")) * 1.0 /
(select count(*) from ( "query2"))
)
from sysibm.sysdummy1;
other solution (be carefull to not divide by 0)
with
query1 as (select count(*) as nb1 from ( "query1")),
query2 as (select count(*) as nb2 from ( "query2"))
select case when nb2=0 then null else nb1* 1.0/nb2 end as Result
from query1, query2

Group by and Count to select repeated rows

I wrote this query but it does not work as I expected.
1st Goal: select rows that have repeated in certain columns and return whole columns.
2nd Goal: Update a flag (a column) to identify which records have repeated.
Could you please help me?
SELECT
*
FROM AvvalV2NS AS M
WHERE EXISTS
(SELECT
M.Astate,
M.Acity,
M.Azone,
M.Abvillage,
M.Avillage,
COUNT(*)
FROM AvvalV2NS AS M
GROUP BY M.Astate,
M.Acity,
M.Azone,
M.Abvillage,
M.Avillage
HAVING COUNT(*) > 1)
If you want to get the rows that are duplicated, window functions are probably the easiest way:
select a.*
from (select a.*,
count(*) over (partition by M.Astate, M.Acity, M.Azone, M.Abvillage, M.Avillage) as cnt
from AvvalV2NS a
) a
where cnt > 1;
You can update a flag by doing something like this:
with toupdate as (
select a.*
from (select a.*,
count(*) over (partition by M.Astate, M.Acity, M.Azone, M.Abvillage, M.Avillage) as cnt
from AvvalV2NS a
) a
)
update toupdate
set isduplicate = (case when cnt > 1 then 1 else 0 end);
Suppose your table have an id column:
SELECT * FROM THE_TABLE WHERE ID IN (
SELECT ID FROM
(SELECT ID, REPEATING_COLUMNS, COUNT(*) FROM THE_TABLE GROUP BY REPEATING_COLUMNS HAVING COUNT(*) > 1)
)
UPDATE THE_TABLE SET THE_FLAG = "HERE WE GO" WHERE ID IN (
SELECT ID FROM
(SELECT ID, REPEATING_COLUMNS, COUNT(*) FROM THE_TABLE GROUP BY REPEATING_COLUMNS HAVING COUNT(*) > 1)
)
Hope this helps.

SQL Server : group by with conditon and give to function

I have this table Test with a column Name in SQL Server:
Name
-----
a
a
a
c
c
b
I wrote this query:
select *
from (select Name, COUNT(*) as cnt
from Test
group by Name
having COUNT(*) > 2) as newTbl
where dbo.fn_Test(Name) = 1
Where dbo.fn_Test a SQL Server scalar function:
CREATE FUNCTION [dbo].[fn_Test]
(#name nvarchar)
RETURNS bigint
AS
BEGIN
DECLARE #count int
SET #count = (SELECT TOP 1 COUNT(*)
FROM Tbl
WHERE Name = #name);
return #count;
END
From first query FROM part is plain that this select get:
select Name, COUNT(*) as cnt
from Test
group by Name
having COUNT(*) > 2
Output:
Name cnt
--------
a 3
But when debug the query and enter to the dbo.fn_Test function it work for all names:
a b c
So how to create select in order to get only name "a" in function?
insert you first select into #t
insert into #t
select Name, COUNT(*) as cnt
from Test
group by Name
having COUNT(*) > 2)
and then use cursor to call the func
...select dbo.fn_Test(#cursor)
Try this
Select Name,Count(Name) from test
Group by Name
having Count(Name)>2
I find solution. This is my solution.
select Name, COUNT(*) as cnt
into #tmpTbl
from Tbl
group by Name
having COUNT(*) > 2
select *
from #tmpTbl
where dbo.fn_Test(Name) = 1
And in fn_Test function I get Names which is correspond to conditions.

How to select a record if the query returns one row, or select no record if the query returns more rows?

I require to select a row if there is only one row exists, if there are more rows, it should select 0 rows.
If you're using PL/SQL, then selecting the column using select-into will throw a too_many_rows exception if there's more than one row returned:
declare
var table.column%type;
begin
select column
into var
from table
where ...;
end;
If you want to do this just using SQL, then you can do something like:
select *
from
(select s.*, count(*) over () c
from
(select *
from table
where ...
and rownum <= 2
) s
)
where c = 1
UPDATE
As DazzaL says in the comments, the reason for the rownum <= 2 restriction is to short-circuit the query if there's more than 2 rows in the result set. This can give significant performance benefits if the dataset is large.
I came up with this, just for the heck of it, using a CTE
With counter as
( select count(any_field) as cnt from your_query
)
SELECT
your_query
WHERE exists (SELECT cnt from Counter WHERE cnt=1)
1 row when there's 1 record - http://sqlfiddle.com/#!4/84c7b/2
0 rows when more than 1 rec - http://sqlfiddle.com/#!4/95c4a/1
EDIT
or if you want to avoid repeating the whole query... an example :
(using the schema from sqlfiddle http://sqlfiddle.com/#!4/6a2d8/117 )
With results as
( select * from montly_sales_totals
),
counter as
( SELECT count(name) as cnt FROM results
)
SELECT *
FROM results
WHERE exists (SELECT cnt from Counter WHERE cnt=5)
SELECT fld1, fld2
FROM (SELECT COUNT(*) over() cnt ,fld1, fld2 FROM tbl WHERE fld1 = 'key')
WHERE cnt = 1
I require to select a row if there is only one row exists, if there
are more rows, it should select 0 rows.
I assume the table contains only the row(s) you are interested to see (or not to see), in that case I would write something like
select *
from table1
where 1 = (select count(1)
from table1
)
In case you want to see only one row from a subset of results from your table, I would go for something like:
with t as ( select *
from table1
where [put here your condition]
)
select *
from t
where 1 = (select count(1)
from t
)
Try this:
SELECT f1,f2
FROM Table
WHERE (f1 = #f1) AND (f2=#f2) AND (f3=#f3)
GROUP BY f1,f2
HAVING (COUNT(*) = 1)
DECLARE COL_COUNT NUMBER;
BEGIN
COL_COUNT: = 0 ;
SELECT COUNT (1) INTO COL_COUNT FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '(ur table name)';
IF COL_COUNT = 0 THEN
EXECUTE IMMEDIATE ('select * from dual') ;
END IF;
END;
Try this:
SELECT col1, col2 FROM
(SELECT count(id) as 'cnt', col1, col2 FROM table_name WHERE col1='value')
WHERE cnt=1;

How to get rows from a table if total rows are more than 10 in Oracle?

I want to write a Oracle based query where I can choose if I want to see the results. Let's say:
SELECT *
FROM table
//when there are more than 10 rows
How can I do this?
select * from table
where 10 < (select count(*) from table)
Best speed:
select * from table
where 10=(select count(*) from
table
where rownum <11)
:)
UPDATE: Because there are suspicions that I claim something that is not true, here some tests:
In SQL Developer(keep in mind that select * from table will offer only first 50 rows, but count(*) read all requested rows)
The table has no indexes.
select
count(*) from
table
22074412 rows
3.16 seconds
select * from table where 10 =
(select
count(*) from
table
where rownum <11
)
0.051 seconds
select * from table where 10 <
(select
count(*) from
table
)
3.39 seconds
select count(*) from table where 10 <
(select
count(*) from
table
)
7.69 seconds
select count(*) from table where 10 =
(select
count(*) from
table
where rownum <11
)
3.42 seconds
Cause: Subquery with rownum is faster (it reads not the entire table)
DECLARE #Var int;
SET #Var = SELECT COUNT(*) FROM [somewhere]
IF #Var > 10
BEGIN
SELECT * FROM [somewhere]
END
You mean something like that?
Or just how to use the where clause?
SELECT *
FROM [somewhere]
WHERE (SELECT COUNT(*) FROM [somewhere]) > 10
This should do it for you:
SELECT * FROM [table] WHERE (SELECT COUNT(1) FROM [table]) > 10
select * from YourTable where (select count(*) from YourTable ) > 10
if you would like to avoid double scans and you have valid statistics you can
select * from table a, all_tables b
where b.num_rows > 10
and b.table_name = 'table';