I'm trying to categorize my data based on the existence of text within a variable for each id that I have. For example:
ID Groupname
1 A
1 B
1 F
2 D
2 B
2 C
The result I want would be
ID Groupname Category
1 A AF
1 B AF
1 F AF
2 D D
2 B D
2 C D
I want to do something like the following but I cannot get it to work
Select * ,
CASE WHEN A,F in groupname (partition by id) THEN AF
WHEN D in groupname (partition by id) THEN D
....
ELSE null END
FROM table
Answers in postgres/redshift would greatly be appreciated!
EDIT:
I fixed the problem with F that JNevill brought up.
EDIT2:
One user suggested a simple solution that works if you only need 1 combination. E.g. If i see F or A then it's AF. But if I need to see A and F it will not work.
Here is the simple solution:
WHEN sum(CASE WHEN combo in (20,28,19,27) then 1 end) over (partition by log_id)=1 then 1000
If i want combinations I have to do the following which creates very long code. Is there an easier way to do this?
WHEN sum(CASE WHEN combo in (20,28,19,27) then 1 end) over (partition by log_id)=1
and sum(CASE WHEN groupid in (1048,598,428) then 1 end) over (partition by log_id)=1
then 1000
you're right about case with partitioning, it just requires conditional aggregate
select
*
,case
when sum(case when groupname in ('A','F') then 1 end) over (partition by id)=1 then 'AF'
when sum(case when groupname in ('D') then 1 end) over (partition by id)=1 then 'D'
end as category
from t
one note is that if you want only the pair of A and F to make AF category it's not possible with this syntax... count(distinct case...) over () returns an error and requires more complex query, but from what I see you don't need it since F is not in your sample data
Related
I will make this question as more precise
I have this data
id product count
1 a 10
1 b 20
1 c 10
1 d 30
I want the result like
Since both product A and B has values i want to count them as one so the result should count(distinct A,C,D) that is 3
If any of product that is (A has values but B does not or vice versa ) then also the result has to be 3
in case both product A and B does not have value then the result should be 2
how to achieve this by using a case statement in oracle plsql
I'm not sure how you define either count of a or either count of b not both, but if you defined it explicitly then you can try this one:
with t as (
select 1 as id, 'a' as product from dual
union all
select 1 as id, 'b' as product from dual
union all
select 1 as id, 'c' as product from dual
union all
select 1 as id, 'd' as product from dual
) select id,
product,
count( case when product in ('c', 'd', 'a') then 1 end ) --change 'a' to 'b' to get the the result for 'b'
from t
group by id, product;
I have gone through a similar post in Stack overflow...
but my query is :
If my table generates a flag in run time execution,then how can I increase Grp_number(generate run time) every time my flag changes.
my Oracle query:
Select emp_id,
Case when MOD(rownum/3)=1 and rownum>1 then 'Y' else 'N' as flag
from Transaction_table
Desired o/p Data format:
emp_id Flag GRP_number
1 N 1
2 N 1
3 N 1
4 Y 2
5 N 2
6 N 2
7 Y 3
You cannot reference a column in another column in the same select list. You need to use sub query to avoid INVALID IDENTIFIER error.
Do it like -
WITH DATA AS(
SELECT emp_id,
CASE
WHEN MOD(rownum/3)=1
AND rownum >1
THEN 'Y'
ELSE 'N' AS flag
FROM Transaction_table
)
SELECT emp_id, flag, SUM(gap) over (PARTITION BY person
ORDER BY DAY) grp
FROM(
SELECT emp_id, flag,
CASE WHEN flag = lag(flag) over (PARTITION BY person
ORDER BY DAY)
THEN 0
ELSE 1
END gap
FROM DATA)
How can I display 0 if there is no qualification matching?
My current query is:
select s.sname, count(*) as number
from sailor s, boat b
where s.rating >= b.rating
group by s.sname
order by number desc;
And the result I got is:
a 3
b 3
c 2
However, it is not really what I am trying to achieve. I would like to display the result like this:
a 3
b 3
c 2
d 0
e 0
I try to change count() to isnull(count(), 0) or coalesce(count(*), 0) but it doesnt correct in this case.
CREATE TABLE sailor (
sname character varying primary key,
rating integer
);
create table boat (
bname character varying primary key,
color character varying,
rating integer
);
This may help you
select s.sname,(select count(*)
from boat b
where s.rating >= b.rating
) t
from sailor s
order by t desc;
SQLFIDDLE
You are using an inner join, which returns only rows when data in both tables matches.
To return sailors without any matching boat, use an outer join:
select s.sname, count(*) as number
from sailor s
left join boat b on s.rating >= b.rating
group by s.sname
order by number desc;
I don't know if I'm being dumb here but I can't seem to find an efficient way to do this. I wrote a very long and inefficient query that does what I need, but what I WANT is a more efficient way.
I have 2 result sets that displays an ID (a PK which is generic/from the same source in both sets) and a FLAG (A - approve and V - Validate).
Result Set 1
ID FLAG
1 V
2 V
3 V
4 V
5 V
6 V
Result Set 2
ID FLAG
2 A
5 A
7 A
8 A
I want to "merge" these two sets to give me this output:
ID FLAG
1 V
2 (V/A)
3 V
4 V
5 (V/A)
6 V
7 A
8 A
Neither of the 2 result sets will at any time have all the ID's to make a simple left join with a case statement on the other result set an easy solution.
I'm currently doing a union between the two sets to get ALL the ID's. Thereafter I left join the 2 result sets to get the required '(V/A)' by use of a case statement.
There must be a more efficient way but I just can't seem to figure it out now as I'm running low on amps... I need a holiday... :-/
Thanks in advance!
Use a FULL OUTER JOIN:
SELECT ID,
CASE
WHEN t1.FLAG IS NULL THEN t2.FLAG
WHEN t2.FLAG IS NULL THEN t1.FLAG
ELSE '(' || t1.FLAG || '/' || t2.FLAG || ')'
END AS MERGED_FLAG
FROM TABLE1 t1
FULL OUTER JOIN TABLE2 t2
USING (ID)
ORDER BY ID
See this SQLFiddle.
Share and enjoy.
I think that you can use xmlagg. Here an exemple :
SELECT deptno,
SUBSTR (REPLACE (REPLACE (XMLAGG (XMLELEMENT ("x", ename)
ORDER BY ename),'</x>'),'<x>','|'),2) as concated_list
FROM emp
GROUP BY deptno
ORDER BY deptno;
Bye
Here is my table and data of these tables
Table name: Code
CID Code
1 abc
2 def
3 xyz
Table Name : Details
ID Name CID
1 a 1
2 b 2
Resultant Table:
ID Code Name
1 abc a
2 abc Null
3 def b
4 def Null
5 xyz Null
6 xyz Null
I nned to get all record from the code table and against each code I have to get all the rows from the details table, if some code have value their need value and if not then Null
Thanks
Sounds like you're looking for the cartesian product:
SELECT
c.CID * d.ID AS ID,
c.Code,
CASE
WHEN c.CID = d.CID THEN d.Name
ELSE NULL
END AS Name
FROM Code c
CROSS JOIN Details d
Although cartesian products are quite slow for larger tables... so be sure that this is what you really want.