Sql view with column identifier - sql

I am creating a select query with union of three tables....
like this
select a as A,b as B c as C where c = x union
select b as A,d as B e as C where e = y and d = a union
select f as A,g as B,h as C
and the result of query is like this:
A B C
===========
1 abc ...
55 def ...
1 sas ...
so I want to have a column that count the number of row, just to prevent the repetition of identifier.
Somthing like this
Row A B C
================
1 1 abc ...
2 55 def ...
3 1 sas ...
....
My question is how it can be done?

You can use ROW_NUMBER() like this:
SELECT ROW_NUMBER() OVER (ORDER BY A,B,C) AS RowNo, *
FROM
(
select a as A,b as B c as C where c = x
union
select b as A,d as B e as C where e = y and d = a
union
select f as A,g as B,h as C
) x

CREATE VIEW dbo.vname
AS
SELECT [Row] = ROW_NUMBER() OVER (ORDER BY A), A, B, C FROM
( <UNION query here> ) AS x;
Replace ORDER BY A with whatever ordering you'd like to see applied. Note that you will need to use ORDER BY on the outer query against dbo.viewname to guarantee that Row will come out in that order.

You can use a common table expression to achieve this:
WITH unionTable
AS
(
select a as A, b as B, c as C where c = x union
select b as A, d as B, e as C where e = y and d = a union
select f as A, g as B, h as C
)
SELECT ROW_NUMBER() OVER (ORDER BY A) AS RowNumber, *
FROM unionTable

Related

Select rows based on values in query

My table :
id
role
b
f
b
s
b
g
a
s
a
f
c
f
I want a distinct id but with corresponding role, with this logic:
If g exists select g if not
if s exists select s if not
if f exists select f.
Query should yield :
id
role
b
g
a
s
c
f
I tried group by id, but role cannot be sorted in a useful order.
select id
,role
from (
select *
,rank() over(partition by id order by case when role = 'g' then 2 when role = 's' then 1 end desc) as rnk
from t
) t
where rnk = 1
id
role
a
s
b
g
c
f
Fiddle

Oracle SQL - Delete Entries Based Off Unique Rows

I am pulling a single column from a DB and it looks something like this:
Group
A
A
A
B
B
B
C
D
D
D
E
F
F
F
I need to delete unique entries, so entries A, B, D and F should stay and entries C and E should be deleted.
I am getting this row based of a query like this:
select Group from table where type = 'rec';
and basically each type should have more than one group and if it doesn't it needs to be removed.
NOTE: I need it to be automated and not just a "remove C" and "remove E" because there are thousands of rows and I'm not sure which I will need to delete unless I just find them. The number of rows that will need to be deleted will also be changing, hence why I need it to be automated based off of count.
One method is:
delete t
where "group" in (select "group" from t group by "group" having count(*) = 1);
Based on your sample code:
delete t
where type = 'rec' and
"group" in (select "group" from t where type = 'rec' group by "group" having count(*) = 1);
You could also do this as:
delete t
where type = 'rec' and
not exists (select 1
from t t2
where t2.group = t.group and t2.type = 'rec' and t2.rowid <> t.rowid
);
Judging by your comments all you need is running total. If entry occurred once then select/delete it. The analytic functions is the best and easiest way if you ask me:
SELECT * FROM
(
SELECT COUNT(grp) OVER (PARTITION BY grp ORDER BY grp) cnt -- number of occurances --
, grp
FROM
( -- convert to multi-row - REPLACE AAABBB with your actual column --
SELECT trim(regexp_substr('A A A B B B C D D D E F F F', '[^ ]+', 1, LEVEL)) grp
FROM dual -- from your table_name --
CONNECT BY LEVEL <= regexp_count('A A A B B B C D D D E F F F', '[^ ]+')
)
)
WHERE cnt = 1 -- Select/Delete only those that appeared once --
/
Output:
cnt|grp
--------
1 C
1 E
Full output, if you comment where:
cnt|grp
--------
3 A
3 A
3 A
3 B
3 B
3 B
1 C
3 D
3 D
3 D
1 E
3 F
3 F
3 F
Final edit based on your questions. This simulates your table:
WITH your_table AS
(
SELECT 'rec' grp_type FROM dual
UNION ALL
SELECT 'not_rec' grp_type FROM dual
)
SELECT grp_type FROM your_table WHERE grp_type = 'rec' -- apply all that above to this select --
/

unique records by one column

I have been working on this for a long time now and cant get the answer.
I have a table with 4 columns. I need to return two of these columns, A and B.
However I need the data to be filtered by the first column A. A is not a primary key. How can I achieve this? If I can return all the columns its also ok, as long as the data is only filtered by column A.
A B C D
1 e f r
1 e f r
1 e k t
2 c f r
2 c f r
3 l f r
This should return
A B C D
1 e f r
2 c f r
3 l f r
Which query wil give me this result? Until now I have this but it does not work well:
SELECT DISTINCT A, B, FROM myTable WHERE C=f
You could use Row_Number() to rank the rows within each distinct A value, then get the first row of each.
SELECT
a, b, c, d
FROM
(SELECT
a, b, c, d,
Row_Number() OVER (PARTITION BY a ORDER BY b, c, d) rn
FROM
myTable) mt
WHERE
rn = 1
Try
SELECT A,B FROM myTable WHERE C='f' GROUP BY A,B
use this
with cte as
(
select * , row_Number() over (Partition by A order by A) as aa from myTable
)
select * from cte where aa = 1

Need help constructing a query to group related elements

I have a table containing the IDs of elements that are related.
ID1 ID2
A B
A C
B D
B C
E F
G D
G C
H I
D C
The example contains the following groups:
A,B,C,D,G
E,F
H,I
Since A is connected to B,C, B is connected to C,D and D is connected to G.
E,F and H,I are only related to each other.
Is it possible to find these groups using SQL? Not sure what the output of the SQL would be, maybe something like this:
ID group
A 1
B 1
C 1
D 1
G 1
E 2
F 2
H 3
I 3
Probably some form of hierarchical query will do the trick but those usually baffle me.
As long as I can discriminate between groups.
Here is what I found:
select root2 || ', ' || listagg(id1, ', ') within group (order by id1) grp
from
(
select id1, max(root2) keep (dense_rank last order by lev) root2
from
(
select t.*, connect_by_root id2 root2, level lev
from <my_table> t
connect by prior t.id1 = t.id2
)
group by id1
)
group by root2
;
This gives:
**GRP**
C, A, B, D, G
F, E
I, H

SQL grouping

I have a table with the following columns:
A B C
---------
1 10 X
1 11 X
2 15 X
3 20 Y
4 15 Y
4 20 Y
I want to group the data based on the B and C columns and count the distinct values of the A column. But if there are two ore more rows where the value on the A column is the same I want to get the maximum value from the B column.
If I do a simple group by the result would be:
B C Count
--------------
10 X 1
11 X 1
15 X 1
20 Y 2
15 Y 1
What I want is this result:
B C Count
--------------
11 X 1
15 X 1
20 Y 2
Is there any query that can return this result. Server is SQL Server 2005.
I like to work in steps: first get rid of duplicate A records, then group. Not the most efficient, but it works on your example.
with t1 as (
select A, max(B) as B, C
from YourTable
group by A, C
)
select count(A) as CountA, B, C
from t1
group by B, C
I have actually tested this:
SELECT
MAX( B ) AS B,
C,
Count
FROM
(
SELECT
B, C, COUNT(DISTINCT A) AS Count
FROM
t
GROUP BY
B, C
) X
GROUP BY C, Count
and it gives me:
B C Count
---- ---- --------
15 X 1
15 y 1
20 y 2
WITH cteA AS
(
SELECT
A, C,
MAX(B) OVER(PARTITION BY A, C) [Max]
FROM T1
)
SELECT
[Max] AS B, C,
COUNT(DISTINCT A) AS [Count]
FROM cteA
GROUP BY C, [Max];
Check this out. This should work in Oracle, although I haven't tested it;
select count(a), BB, CC from
(
select a, max(B) BB, Max(C) CC
from yourtable
group by a
)
group by BB,CC