oracle sql group count - sql

SELECT a,b,count(*)
FROM t
GROUP BY rollup(a,b)
result:
a1, b1, 10
a1, b2, 90
a1, , 100
i need:
a1, b1, 10, 100
a1, b2, 90, 100
how?

This table simulates your situation:
SQL> create table t (a,b)
2 as
3 select 'a1', 'b1'
4 from dual
5 connect by level <= 10
6 union all
7 select 'a1', 'b2'
8 from dual
9 connect by level <= 90
10 /
Table created.
Your result with only three rows misses the grand total, so that's a little inaccurate: rollup(a,b) results in 3 grouping sets with 4 rows.
SQL> select a
2 , b
3 , count(*)
4 from t
5 group by rollup(a,b)
6 /
A B COUNT(*)
-- -- ----------
a1 b1 10
a1 b2 90
a1 100
100
4 rows selected.
With a regular group by and an analytic function on top, you can achieve your desired result set:
SQL> select a
2 , b
3 , count(*)
4 , sum(count(*)) over (partition by a)
5 from t
6 group by a
7 , b
8 /
A B COUNT(*) SUM(COUNT(*))OVER(PARTITIONBYA)
-- -- ---------- -------------------------------
a1 b2 90 100
a1 b1 10 100
2 rows selected.
Regards,
Rob.

Use:
SELECT t.a,
t.b,
COUNT(*),
(SELECT COUNT(*)
FROM YOUR_TABLE
GROUP BY t.a)
FROM YOUR_TABLE t
GROUP BY t.a, t.b

Related

Oracle: Analytical functions Sub totals after each change in value

I have the following data (order of records as in the example):
A B
1 10
1 20
1 30
1 40
2 50
2 65
2 75
1 89
1 100
from SQL:
with x as (
select A, B
from (
select 1 as A, 10 as B from dual
union all
select 1 as A, 20 as B from dual
union all
select 1 as A, 30 as B from dual
union all
select 1 as A, 40 as B from dual
union all
select 2 as A, 50 as B from dual
union all
select 2 as A, 65 as B from dual
union all
select 2 as A, 75 as B from dual
union all
select 1 as A, 89 as B from dual
union all
select 1 as A, 100 as B from dual
)
)
select A, B
from X
I want to group the data for each change of value in column A,
I want to get the following result:
A MIN(B) MAX(B)
1 10 40
2 50 75
1 89 100
How to get such a result in the ORACLE 11. I would expect a simple implementation...
This is a gaps and islands problem, solved using row_number analytic function
SELECT a,
MIN(b),
MAX(b)
FROM (
SELECT x.*,
ROW_NUMBER() OVER(
ORDER BY b
) - ROW_NUMBER() OVER(
PARTITION BY a
ORDER BY b
) AS seq
FROM x
)
GROUP BY a,
seq;
Demo

How to combine and count two columns in oracle?

My table seems like this;
A B
1 100
1 102
1 105
2 100
2 105
3 100
3 102
I want output like this:
A Count(B)
1 3
1,2 2
1,2,3 3
2 2
3 2
2,3 2
How can i do this?
I try to use listagg but it didn't work.
I suspect that you want to count the number of sets of A that are in the data -- and that your sample results are messed up.
If so:
select grp, count(*)
from (select listagg(a, ',') within group (order by a) as grp
from t
group by b
) b;
This gives you the counts for the full combinations present in the data. The results would be:
1,2,3 1
1,3 1
1,2 1
You can get the original number of rows by doing:
select grp, sum(cnt)
from (select listagg(a, ',') within group (order by a) as grp, count(*) as cnt
from t
group by b
) b;
Oracle Setup:
CREATE TABLE table_name ( A, B ) AS
SELECT 1, 100 FROM DUAL UNION ALL
SELECT 1, 102 FROM DUAL UNION ALL
SELECT 1, 105 FROM DUAL UNION ALL
SELECT 2, 100 FROM DUAL UNION ALL
SELECT 2, 105 FROM DUAL UNION ALL
SELECT 3, 100 FROM DUAL UNION ALL
SELECT 3, 102 FROM DUAL;
Query:
SELECT A,
COUNT(B)
FROM (
SELECT SUBSTR( SYS_CONNECT_BY_PATH( A, ',' ), 2 ) AS A,
B
FROM table_name
CONNECT BY PRIOR B = B
AND PRIOR A + 1 = A
)
GROUP BY A
ORDER BY A;
Output:
A COUNT(B)
----- ----------
1 3
1,2 2
1,2,3 1
2 2
2,3 1
3 2

Simplest way to repeat every N rows in sql

I know this is possible through some complex techniques, i want to know any simplest way to achieve this patter that every 10 rows should repeat .
for example
select a,b from tablename; (repeating 2 for example)
will give
a1,b1
a2,b2
a1,b1
a2.b2
a3,b3
a4,b4
a3,b3
a4,b4
where if it was 10 it will go like
a1,b1 to a10,b10 again a1,b1 to a10,b10
then
a11,b11 to a20,b20 again a11,b11 to a20,b20
and so on
You want blocks of ten rows repeated twice. So to get:
rows 1 to 10
rows 1 to 10
rows 11 to 20
rows 11 to 20
...
In order to get rows n-fold cross join with a table holding n records. (You get such for instance by querying a big enough table and stop at rowcount n.)
You also need the row number of your original records, so you can get block 1 first, then block 2 and so on. Use integer division to get from row numbers to blocks.
select t.a, t.b
from (select a, b, row_number() over (order by a, b) as rn from tablename) t
cross join (select rownum as repeatno from bigenoughtable where rownum <= 2) r
order by trunc((t.rn -1) / 10), r.repeatno, t.a, t.b;
Use a CTE and union all:
with rows as (
select a, b
from tablename
where rownum <= 2
)
select *
from rows
union all
select *
from rows;
Just some caveats to this. You should use an order by if you want particular rows from the table. This is important, because the same select can return different sets of rows. Actually, considering this, a better way is probably:
with rows as (
select a, b
from tablename
where rownum <= 2
)
select *
from rows cross join
(select 1 as n from dual union all select 2 from dual) n;
I would rather not use UNION so many times. My way would be CONNECT BY ROWNUM <=N. Actually a CARTESIAN JOIN. So, basically you need a ROW GENERATOR to cartesian join with it.,
Update
For example, this will repeat 10 rows 2 times -
SQL> WITH t AS
2 ( SELECT 'a1' A, 'b1' b FROM dual
3 UNION ALL
4 SELECT 'a2' a, 'b2' b FROM dual
5 UNION ALL
6 SELECT 'a3' a, 'b3' b FROM dual
7 UNION ALL
8 SELECT 'a4' A, 'b4' b FROM dual
9 UNION ALL
10 SELECT 'a5' A, 'b5' b FROM dual
11 UNION ALL
12 SELECT 'a6' a, 'b6' b FROM dual
13 UNION ALL
14 SELECT 'a7' A, 'b7' b FROM dual
15 UNION ALL
16 SELECT 'a8' a, 'b8' b FROM dual
17 UNION ALL
18 SELECT 'a9' a, 'b9' b FROM dual
19 UNION ALL
20 SELECT 'a10' a, 'b10' b FROM dual
21 )
22 SELECT A,B FROM t,
23 (SELECT 1 FROM DUAL CONNECT BY ROWNUM <=2
24 )
25 /
A B
--- ---
a1 b1
a2 b2
a3 b3
a4 b4
a5 b5
a6 b6
a7 b7
a8 b8
a9 b9
a10 b10
a1 b1
a2 b2
a3 b3
a4 b4
a5 b5
a6 b6
a7 b7
a8 b8
a9 b9
a10 b10
20 rows selected.
SQL>
So, above CONNECT BY ROWNUM <=10 means repeat the rows 10 times. If you want it to be repeated N times use CONNECT BY ROWNUM <=N.

Oracle query to select rows with unique code

I have a table like this
C1 C2 C3 Code
1 2 3 33
1 2 3 34
2 4 1 14
1 2 3 14
i want to select only those record whose code is appearing only in single row. ie, in this case rows with code 33 and 34.. as they appear only once in this table.
How can i write a query for that
If you want only one pass over your data, then you can use this query:
SQL> create table mytable (c1,c2,c3,code)
2 as
3 select 1, 2, 3, 33 from dual union all
4 select 1, 2, 3, 34 from dual union all
5 select 2, 4, 1, 14 from dual union all
6 select 1, 2, 3, 14 from dual
7 /
Table created.
SQL> set autotrace on
SQL> select max(c1) c1
2 , max(c2) c2
3 , max(c3) c3
4 , code
5 from mytable
6 group by code
7 having count(*) = 1
8 /
C1 C2 C3 CODE
---------- ---------- ---------- ----------
1 2 3 33
1 2 3 34
2 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 FILTER
2 1 SORT (GROUP BY)
3 2 TABLE ACCESS (FULL) OF 'MYTABLE'
Regards,
Rob.
SELECT C1, C2, C3, Code FROM tablename
WHERE Code IN
(
SELECT Code FROM tablename
GROUP BY Code
HAVING count(Code) = 1
)
select C1, C2, C3, Code
from tablename T1
where not exists ( select T2.exclude
from tablename T2
where T2.Code = T1.Code
and T2.rowid <> T1.rowid
)
PS. Watch out for NULL values in the Code column

table join where

Table1 t10 (id)
id
---
1
2
table t11(a1,a2,a3)
a1 a2 a3
----------
1 10 a
1 10 b
1 11 b
1 12 c
2 20 d
2 21 e
select * from t10 a,t11 b where a.id = b.a1
how to display
id a1 a2 a3
--------------
1 1 10 a
1 1 10 b //(not display this row)
1 1 11 b //(not display this row)
1 1 12 c //(not display this row)
2 2 20 d
2 2 21 e //(not display this row)
just get t11's random row
maybe display this
id a1 a2
----------
1 1 11 b
1 1 10 a //(not display this row)
1 1 10 b //(not display this row)
1 1 12 c //(not display this row)
2 2 20
2 2 21 //(not display this row)
select a1 as id, a1, min(a2) as a2
from t11
group by a1
will give you:
id a1 a2
----------
1 1 10
2 2 20
This seems almost like he wants something like FIRST/LAST from ms access.
This can ben done (very closely) in Sql Server using
DECLARE #Table TABLE(
id INT,
a1 INT,
a2 INT
)
INSERT INTO #Table (id,a1,a2) SELECT 1, 1, 11
INSERT INTO #Table (id,a1,a2) SELECT 1, 1, 10
INSERT INTO #Table (id,a1,a2) SELECT 1, 1, 12
INSERT INTO #Table (id,a1,a2) SELECT 2, 2, 20
INSERT INTO #Table (id,a1,a2) SELECT 2, 2, 21
SELECT *
FROM #Table t
WHERE a2 = (SELECT TOP 1 a2 FROM #Table WHERE id = t.id AND a1 = t.a1)
This is the answer:
SELECT *
FROM t10 a, (
SELECT * FROM (
SELECT b.*, ROW_NUMBER() OVER(PARTITION BY a10 ORDER BY a10) as rn
FROM t11 b
) WHERE rn =1) b
WHERE a.id = b.a10(+)