How to get mean of exams by client with 2 tables? - sql

I know a little bit of sql, only the basic, now I need to create a analytic query but can't do this yet.
I have 2 tables on my db oracle, client and exams:
I am tried a lot of ways to get the mean of exams by client, but no success yet.4
The result expected is:
exams = 13
clients = 6
13/6= 2.166666666...7
How can I do that?

If you have clients who have not taken any exams then you want:
SELECT AVG(COUNT(e.nu_ordem)) AS avg_exames_by_client
FROM cliente c
LEFT OUTER JOIN exames e
ON (c.id = e.id_cliente)
GROUP BY c.id;
or:
SELECT (SELECT COUNT(*) FROM exames) / (SELECT COUNT(*) FROM cliente)
AS avg_exames_by_client
FROM DUAL;
Which, for the sample data:
CREATE TABLE cliente (id PRIMARY KEY) AS
SELECT 1 FROM DUAL UNION ALL
SELECT 2 FROM DUAL UNION ALL
SELECT 3 FROM DUAL UNION ALL
SELECT 4 FROM DUAL UNION ALL
SELECT 5 FROM DUAL UNION ALL
SELECT 6 FROM DUAL;
CREATE TABLE exames (nu_ordem PRIMARY KEY, id_cliente) AS
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 2, 5 FROM DUAL UNION ALL
SELECT 3, 5 FROM DUAL UNION ALL
SELECT 4, 2 FROM DUAL UNION ALL
SELECT 5, 6 FROM DUAL UNION ALL
SELECT 6, 1 FROM DUAL UNION ALL
SELECT 7, 1 FROM DUAL UNION ALL
SELECT 8, 4 FROM DUAL UNION ALL
SELECT 9, 5 FROM DUAL UNION ALL
SELECT 10, 3 FROM DUAL UNION ALL
SELECT 11, 6 FROM DUAL UNION ALL
SELECT 12, 2 FROM DUAL UNION ALL
SELECT 13, 1 FROM DUAL;
Both output:
AVG_EXAMES_BY_CLIENT
2.166666666666666667
If you then add a couple of clients but no more exams:
INSERT INTO cliente (id)
SELECT 7 FROM DUAL UNION ALL
SELECT 8 FROM DUAL
Then the average is:
AVG_EXAMES_BY_CLIENT
1.625
db<>fiddle here

You can try below formula to get the result -
SELECT COUNT(*)/COUNT(DISTINCT id_cliente)
FROM exams;

Related

Having a node at level N

I want to write the code by Having a node at level N (for example 3) of the tree, find all members up to level M (for example 6).How can I write this code? what is the best idea for this problem?
I am new in oracle , please explain me and help me for resolve this problem .
CREATE TABLE tree (
node_id INT,
parent_id INT
)
INSERT INTO
tree
SELECT 1, NULL FROM DUAL
UNION ALL SELECT 2, 1 FROM DUAL
UNION ALL SELECT 3, 1 FROM DUAL
UNION ALL SELECT 4, 2 FROM DUAL
UNION ALL SELECT 5, 2 FROM DUAL
UNION ALL SELECT 6, 3 FROM DUAL
UNION ALL SELECT 7, 3 FROM DUAL
UNION ALL SELECT 8, 4 FROM DUAL
UNION ALL SELECT 9, 4 FROM DUAL
UNION ALL SELECT 10, 5 FROM DUAL
UNION ALL SELECT 11, 5 FROM DUAL
UNION ALL SELECT 12, 6 FROM DUAL
UNION ALL SELECT 13, 6 FROM DUAL
UNION ALL SELECT 14, 7 FROM DUAL
UNION ALL SELECT 15, 7 FROM DUAL
15 rows affected
SELECT
node_id, parent_id, level
FROM
tree
WHERE
level < 3
CONNECT BY
PRIOR node_id = parent_id
START WITH
parent_id = 3
ORDER BY
level, node_id
NODE_ID
PARENT_ID
LEVEL
6
3
1
7
3
1
12
6
2
13
6
2
14
7
2
15
7
2
fiddle

Is there a reason I am getting no rows selected for this NOT IN nested query

Query:
SELECT teamid
FROM team
WHERE teamid NOT IN (SELECT team_teamid FROM gymnast);
Tables:
TEAM table
Gymnast table
I have been trying to figure this out for a while, any information would be greatly appreciated. Thank you!
The fiddle for oracle
val NOT IN (some list) means the value does NOT match every entry in the list.
But if one entry in the list is null, value <> null can never be true for that entry, which means the entire NOT IN expression can never be true.
See the following examples:
WITH team (teamid) AS (
SELECT 1 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT 3 FROM DUAL UNION
SELECT 4 FROM DUAL
)
, gymnast (team_teamid) AS (
SELECT 1 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT 4 FROM DUAL
)
SELECT teamid FROM team WHERE teamid NOT IN (SELECT team_teamid FROM gymnast)
;
Result:
TEAMID
3
Case 2 with nulls in the list:
WITH team (teamid) AS (
SELECT 1 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT 3 FROM DUAL UNION
SELECT 4 FROM DUAL
)
, gymnast (team_teamid) AS (
SELECT 1 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT null FROM DUAL UNION
SELECT 4 FROM DUAL
)
SELECT teamid FROM team WHERE teamid NOT IN (SELECT team_teamid FROM gymnast)
;
Result:
TEAMID
No rows in result, due to the gymnast with a null team_teamid.

How to count distinct flags in the sql

BELOW IS SNIPPET OF MY DATA
Here is the sample creation code of testing.
CREATE TABLE MYGROUP ( Category,PERSON,Flag ) AS
SELECT 'Cat1','A','1' FROM DUAL
UNION ALL SELECT 'Cat1','A','0' FROM DUAL
UNION ALL SELECT 'Cat1','A','1' FROM DUAL
UNION ALL SELECT 'Cat1','B','1' FROM DUAL
UNION ALL SELECT 'Cat1','B','0' FROM DUAL
UNION ALL SELECT 'Cat2','A','0' FROM DUAL
UNION ALL SELECT 'Cat2','A','0' FROM DUAL
UNION ALL SELECT 'Cat2','A','0' FROM DUAL
UNION ALL SELECT 'Cat2','B','1' FROM DUAL
UNION ALL SELECT 'Cat2','B','1' FROM DUAL
UNION ALL SELECT 'Cat2','B','0' FROM DUAL
UNION ALL SELECT 'Cat3','X','0' FROM DUAL
UNION ALL SELECT 'Cat3','Y','0' FROM DUAL;
Desired Output:
Category - Count of Distinct Persons with Flag = 1
Cat1 - 2
Cat2 - 1
Cat3 - 0
I need to get my code in Big query to get distinct counts of persons. It shouldnt double count.
You can use conditional aggregation
SELECT
Category,
COUNT(DISTINCT CASE WHEN Flag = 1 THEN PERSON END)
FROM MYGROUP
GROUP BY Category;

How to upside down the result rows of a select statment in oracle?

I can select a list of rows from a table. but I want to show them by swapping upside down.
Explaination:
with table1 as
(
select 1 ID, 'txt1' value from dual
union all
select 2, 'txt2' from dual
union all
select 7, 'txt7' from dual
union all
select 5, 'txt5' from dual
union all
select 3, 'txt3' from dual
)
select * from table1;
in above query I can obtain following result
ID | VALUE
------------------
1 txt1
2 txt2
7 txt7
5 txt5
3 txt3
but I want to show them as follows
ID | VALUE
------------------
3 txt3
5 txt5
7 txt7
2 txt2
1 txt1
How to do that?
One approach would be to add a computed column to your set of union queries, then order by that column:
WITH table1 AS (
SELECT 1 ID, 'txt1' value, 1 AS position FROM dual
UNION ALL
SELECT 2, 'txt2', 2 FROM dual
UNION ALL
SELECT 7, 'txt7', 3 FROM dual
UNION ALL
SELECT 5, 'txt5', 4 FROM dual
UNION ALL
SELECT 3, 'txt3', 5 FROM dual
)
SELECT *
FROM table1
ORDER BY pos DESC;
Note that there is no internal order to a SQL table in general. Actually, even the current ordering you are observing is not necessarily guaranteed by Oracle. If you expect a certain order in a result set, you need to impose it via a ORDER BY clause.
How's this?
with table1 as
(
select 1 ID, 'txt1' value from dual
union all
select 2, 'txt2' from dual
union all
select 7, 'txt7' from dual
union all
select 5, 'txt5' from dual
union all
select 3, 'txt3' from dual
)
select * from table1 order by rownum desc;
Actually this is not working for this perticular example. but it is working for normal table.

Select values is a row as column values

How can I retrieve values in a row as column values?
Example:
Consider the output of below query as INPUT :
Select 1,2,3,4,5,6,7,8,9,10
from dual;
I need a query that can give below output:
COL1
----
1
2
3
4
5
6
7
8
9
10
SELECT 1 AS "COL1" FROM dual
UNION
SELECT 2 FROM dual
UNION
SELECT 3 FROM dual
UNION
SELECT 4 FROM dual
UNION
SELECT 5 FROM dual
UNION
SELECT 6 FROM dual
UNION
SELECT 7 FROM dual
UNION
SELECT 8 FROM dual
UNION
SELECT 9 FROM dual
UNION
SELECT 10 FROM dual ;
If you want to generate a sequence of numbers in Oracle:
with n as (
select level as n
from dual
connect by level <= 10
)
select *
from n;
Or, if you have 10 columns, you can do an unpivot. An easy way is with union all:
select col1 from t union all
select col2 from t union al
. . .
select col10 from t;