I need help converting T-SQL query to Oracle supported query - sql

I am executing this query in SQL Server and it is working fine but when I try to execute it in Oracle, it is not giving the same results.
You can see in my attached photo the data of one customer, which have got the code 1, 2,4, 8 and he should get 0.70 value for having code 1,2,4 and then for having code 8 he should get 0.75 so after multiplication it should return 0.52 as value. I tried it in Oracle by replacing is null by nvl but it returned 1 instead of 0.52. Please help me convert this query in an oracle supported query which will return the same results.
Here is my query
SELECT [id] ,[name],r = isnull(nullif(
max(CASE WHEN [code] IN (1,2,4) then 0.70 else 0 end)
,0),1)
* isnull(nullif(
min(CASE WHEN [code] IN (1,2) then 0 else 1 end)
* max(CASE WHEN [code] IN (4) then 0.20 else 0 end)
,0),1)
* isnull(nullif(
max(CASE WHEN [code] IN (8) then 0.75 else 0 end)
,0),1)
FROM (values (1, 'ali',4)
,(1, 'ali',1)
,(1, 'ali',8)
,(1, 'ali',2)
,(2, 'sunny',1)
,(4, 'arslan',4)) as t(id, name,code)
GROUP BY id, name;

Since now you are multiplying scores, first we need to decide, what is the score if non of codes is matched. I suppose, it should be 0.
Next, we should break all possible codes into independent groups, that is which results do not depend on other groups members. Here they are (1,2,4) and (8). And define the rule for every group.
So
SELECT [id] ,[name],r =
-- At least one of values needed to get score > 0
MAX(CASE WHEN code IN (1,2,4, 8) THEN 1.0 ELSE 0.0 END) *
-- Now rules for every independent set of codes. Rule should return score if matched or 1.0 if not matched
-- (1,2,4)
coalesce(MAX(CASE WHEN [code] IN (1,2,4) THEN 0.70 END), 1.0 ) *
-- (8)
coalesce(MAX(CASE WHEN [code] IN (8) THEN 0.75 END), 1.0)
-- more ?
FROM (values (1, 'ali',4)
,(1, 'ali',1)
,(1, 'ali',8)
,(1, 'ali',2)
,(2, 'sunny',1)
,(4, 'arslan',4)) as t(id, name,code)
GROUP BY id, name;

There are some SQL Server things in the query that are not standard SQL:
[] around column names - remove them; you don't need them here (otherwise you would use standard SQL quotes "")
r = expression - for an alias name. Change this to standard SQL expression AS r
ISNULL(expression, value) - Change this to standard SQL COALESCE(expression, value) or Oracle's NVL(expression, value)
NULLIF(expression, value) - this you can keep; Oracle supports it, too
values (), (), ... - replace with a SELECT FROM DUAL UNION ALL subquery
You get:
select
id,
name,
coalesce(nullif( max(case when code in (1,2,4) then 0.70 else 0 end), 0), 1) *
coalesce(nullif( min(case when code in (1,2) then 0 else 1 end) *
max(case when code in (4) then 0.20 else 0 end) , 0), 1) *
coalesce(nullif( max(case when code in (8) then 0.75 else 0 end), 0), 1) as r
from
(
select 1 as id, 'ali' as name, 4 as code from dual
union all
select 1 as id, 'ali' as name, 8 as code from dual
union all
select 1 as id, 'ali' as name, 2 as code from dual
union all
select 2 as id, 'sunny' as name, 1 as code from dual
union all
select 4 as id, 'arslan' as name, 4 as code from dual
)
group by id, name;
The calculation, however, is unnecessarily complicated:
coalesce(nullif( max(case when code in (1,2,4) then 0.70 else 0 end), 0), 1)
means if there is at least one match then 0.70 else 0 which is turned to null which is turned to 1. So it is the same as
min(case when code in (1,2,4) then 0.70 else 1 end)
So if I am not mistaken, the whole calcultion becomes:
case when max(case when code in (1,2) then 1 end) = 1
then 0.7 else max(case when code = 4 then 0.14 else 1 end) end *
min(case when code = 8 then 0.75 else 1 end) as r
or
case when max(case when code in (1,2) then 1 end) = 1 then 0.7
when max(case when code = 4 then 1 end) = 1 then 0.14
else 1
end *
min(case when code = 8 then 0.75 else 1 end) as r
Well, there are many ways to write this.

The code below should give you the answer you expect;
CREATE TABLE #TestData (ID int, Name varchar(10), Code int)
INSERT INTO #TestData (ID, Name, Code)
VALUES
(1,'ali',4)
,(1,'ali',1)
,(1,'ali',8)
,(1,'ali',2)
,(2,'sunny',1)
,(4,'arslan',4)
SELECT DISTINCT
a.id
,a.Name
,COALESCE(b.HasCode1, b.HasCode2, b.HasCode4,1) * COALESCE(b.HasCode8,1) Result
FROM (SELECT ID, Name FROM #TestData GROUP BY ID, Name) a
LEFT JOIN
(
SELECT
ID
,Name
,SUM(CASE WHEN CODE = 1 THEN 0.7 END) HasCode1
,SUM(CASE WHEN CODE = 2 THEN 0.7 END) HasCode2
,SUM(CASE WHEN CODE = 4 THEN 0.7 END) HasCode4
,SUM(CASE WHEN CODE = 8 THEN 0.75 END) HasCode8
FROM #TestData
GROUP BY
ID
,Name
) b
ON a.ID = b.ID
AND a.Name = b.Name
DROP TABLE #TestData

If I understand what you're after (ie. for each of the cases, the id/name combination needs to have all the codes specified), then this will probably do what you're after. You may want to add some sort of trunc/floor/round function on the val column if you're after the answer to 2 decimal places, though:
with t as (select 1 id, 'ali' name, 4 code from dual union all
select 1 id, 'ali' name, 1 code from dual union all
select 1 id, 'ali' name, 8 code from dual union all
select 1 id, 'ali' name, 2 code from dual union all
select 2 id, 'ali' name, 4 code from dual union all
select 2 id, 'ali' name, 8 code from dual union all
select 3 id, 'bob' name, 1 code from dual union all
select 3 id, 'bob' name, 2 code from dual union all
select 3 id, 'bob' name, 8 code from dual),
res as (select id,
name,
case when count(distinct case when code in (1, 2, 4) then code end) = 3 then 0.7
when count(distinct case when code in (1, 2) then code end) = 2 then 0.5
else 1
end case_1_2_and_poss_4,
case when count(distinct case when code = 8 then code end) = 1 then 0.75 else 1 end case_8
from t
group by id, name)
select id,
name,
case_1_2_and_poss_4 * case_8 val
from res;
ID NAME VAL
---------- ---- ----------
1 ali 0.525
2 ali 0.75
3 bob 0.375

Related

select from table where a=1 and a=2

i have a four requirement (may be four select is ok) where I need to find from single table, if customer has
a. apple and samsung
b. no_apple and no_samsung
c. apple and no_samsung
d. no_apple and samsung
my table be like...
cust_name device
john apple
john samsung
dave apple
tim samsung
patrick nokia
rick nokia
so expect output be like...
a:- output ( both apple and samsung)
count(*)
1
b:-output (no_apple and no_samsung)
count(*)
2
c:-output (apple and no_samsung)
count(*)
1
d:-output (no_apple and samsung)
count(*)
1
You can do it all in a single query using conditional aggregation:
SELECT COUNT(CASE WHEN num_apple > 0 AND num_samsung > 0 THEN 1 END)
AS apple_and_samsung,
COUNT(CASE WHEN num_apple = 0 AND num_samsung > 0 THEN 1 END)
AS no_apple_and_samsung,
COUNT(CASE WHEN num_apple > 0 AND num_samsung = 0 THEN 1 END)
AS apple_and_no_samsung,
COUNT(CASE WHEN num_apple = 0 AND num_samsung = 0 THEN 1 END)
AS no_apple_and_no_samsung
FROM (
SELECT cust_name,
COUNT(CASE device WHEN 'apple' THEN 1 END) AS num_apple,
COUNT(CASE device WHEN 'samsung' THEN 1 END) AS num_samsung
FROM table_name
GROUP BY cust_name
)
Which, for the sample data:
CREATE TABLE table_name (cust_name, device) AS
SELECT 'john', 'apple' FROM DUAL UNION ALL
SELECT 'john', 'samsung' FROM DUAL UNION ALL
SELECT 'dave', 'apple' FROM DUAL UNION ALL
SELECT 'tim', 'samsung' FROM DUAL UNION ALL
SELECT 'patrick', 'nokia' FROM DUAL UNION ALL
SELECT 'rick', 'nokia' FROM DUAL;
Outputs:
APPLE_AND_SAMSUNG
NO_APPLE_AND_SAMSUNG
APPLE_AND_NO_SAMSUNG
NO_APPLE_AND_NO_SAMSUNG
1
1
1
2
You can also do it by PIVOTing twice:
SELECT *
FROM table_name
PIVOT (
COUNT(DISTINCT device) FOR device IN (
'apple' AS apple,
'samsung' AS samsung
)
)
PIVOT (
COUNT(cust_name) FOR (apple, samsung) IN (
(1, 1) AS apple_and_samsung,
(1, 0) AS apple_and_no_samsung,
(0, 1) AS no_apple_and_samsung,
(0, 0) AS no_apple_and_no_samsung
)
)
db<>fiddle here
You might add proper HAVING clauses for each case after GROUPing by cust_name column such as
a)
SELECT COUNT(DISTINCT cust_name)
FROM t
GROUP BY cust_name
HAVING SUM(CASE WHEN device ='apple' THEN 1 ELSE 0 END)
* SUM(CASE WHEN device ='samsung' THEN 1 ELSE 0 END) = 1;
b)
SELECT SUM(COUNT(DISTINCT cust_name))
FROM t
GROUP BY cust_name
HAVING MIN(CASE WHEN device ='apple' THEN 0 ELSE 1 END)
* MIN(CASE WHEN device ='samsung' THEN 0 ELSE 1 END) = 1;
c)
SELECT COUNT(DISTINCT cust_name)
FROM t
GROUP BY cust_name
HAVING MIN(CASE WHEN device ='samsung' THEN 0 ELSE 1 END)
* MIN(CASE WHEN device ='apple' THEN 1 ELSE 0 END) = 1;
d)
SELECT COUNT(DISTINCT cust_name)
FROM t
GROUP BY cust_name
HAVING MIN(CASE WHEN device ='apple' THEN 0 ELSE 1 END)
* MIN(CASE WHEN device ='samsung' THEN 1 ELSE 0 END) = 1
Demo

How to transform and grouping in SQL

I would like to group bycontract date by transforming segment referring to its contract date like below.
contractdate segment
~2020/2/1 a
2020/2/2~2020/4/1 b
2020/4/2~ c
My desired result is to cut contractdate into segment and countthem into result tables.
If someone has opinion,please let me know.
Thanks
my table is like below.
contractdate status
2020/1/2 A
2020/4/2 B
2020/6/5 C
2020/1/2 C
2020/4/4 B
And here is my desired result.
segment A B C
a 1 0 1
b 0 0 0
c 0 2 1
Replace missing bounds with sentinels (or replace notation with weird tilde character at all), then distribute contractdate of statuses into proper ranges:
with sg (contractdate,segment) as (
select '~2020/2/1' , 'a' from dual union all
select '2020/2/2~2020/4/1', 'b' from dual union all
select '2020/4/2~' , 'c' from dual
), ssg as ( -- sanitized sg
select coalesce(to_date(regexp_replace(contractdate,'([^~]*)~([^~]*)','\1'),'YYYY/MM/DD'), date '-4712-1-1') as lowerbound -- source: https://laurentschneider.com/wordpress/2008/01/what-is-the-lowest-and-highest-possible-date-in-oracle.html
, coalesce(to_date(regexp_replace(contractdate,'([^~]*)~([^~]*)','\2'),'YYYY/MM/DD'), date '9999-01-01') as upperbound
, segment
from sg
), st (contractdate,status) as (
select '2020/1/2', 'A' from dual union all
select '2020/4/2', 'B' from dual union all
select '2020/6/5', 'C' from dual union all
select '2020/1/2', 'C' from dual union all
select '2020/4/4', 'B' from dual
)
select segment
, sum(case when status = 'A' then 1 else 0 end)
, sum(case when status = 'B' then 1 else 0 end)
, sum(case when status = 'C' then 1 else 0 end)
from ssg left join st on to_date(st.contractdate,'YYYY/MM/DD') between ssg.lowerbound and ssg.upperbound
group by segment
order by segment
Please use CTE to specify your input data, not plaintext tables. It helps to concentrate on answer instead of text formatting.

SQL Sum Using logic to choose Plus or Minus (Oracle)

Not sure if this is possible or not in straight SQL.
Is it possible to choose the operator for a sum using the likes of a CASE Statement or similar logic.
e.g.
select
(select 1 from dual)
(case when (select 1 from dual) = 1 then + else - end)
(select 2 from dual)
from dual
Thanks in return.
- and + cannot be results of CASE WHEN, because they are not values. -1 and +1 however are. Multiply this -1 or +1 with the desired value in order to get the positive or negative value. E.g:
select case when type = 'withdrawal' then -1 else +1 end * value as balance_change
For your example:
select
(select 1 from dual) +
(case when (select 1 from dual) = 1 then +1 else -1 end) *
(select 2 from dual)
from dual
select 1 + (case when (select 1 from dual) = 1 then +1 else -1 end) from dual
I mean:
with
sub_q as (
select 2000 val1, -1500 val2 from dual
union all
select 1000 val1, +2000 val2 from dual
)
select val1, val2, SIGN(val2) s, val1 + (case when SIGN(val2) = 1 then +val2 else -val2 end) res
from sub_q

SQL Error "Cannot perform an aggregate function on an expression containing an aggregate or a sub query."

I am executing this query in Oracle. I have added the screenshots of my data and the returned results but the returned result is wrong. It is returning 1 but it should return 0.52. Because the customer(see in attached screenshot) have codes 1,2,4,31 and for 1,2,4 he should get 0.70 value and for 31 he should get 0.75 and then after multiplication the returned result should be 0.52 instead of 1.
I am really stuck here. Please help me. I will be very thankful to you.
Here is my query. What I actually want to do is I want to calculate points value given to every customer on the basis of codes they got.
If a customer have code = 1 then he will get 0.70 points and then if he have code = 2 and 4 too then I do not want to give him extra 0.70 for code 2 and 4.
Let me be simple. If a customer have all of these codes 1, 2, 4 then he will only get 0.70 points for once, but if he have code 4 only then he will get 0.90, but if he got code 31 too then he will get extra 0.75 for having code 31. Does it make sense now?
SELECT
RM_LIVE.EMPLOYEE.EMPNO, RM_LIVE.EMPNAME.FIRSTNAME,
RM_LIVE.EMPNAME.LASTNAME, RM_LIVE.CRWBASE.BASE ,RM_LIVE.CRWCAT.crwcat AS "Rank",
nvl(nullif(MAX(CASE WHEN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN (29,721) THEN 0.25 ELSE 1 END),0),1) *
nvl(nullif(MAX(CASE WHEN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN (31,723) THEN 0.75 ELSE 1 END),0),1) *
nvl(nullif(MAX(CASE WHEN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC = 861 THEN 0.80 ELSE 1 END),0),1) *
nvl(nullif(MAX(CASE WHEN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN (17,302,16) THEN 0.85 ELSE 1 END),0),1) *
nvl(nullif(MAX(CASE WHEN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN (3,7) THEN 0.90 ELSE 1 END),0),1)*
nvl(nullif(MAX(CASE WHEN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN (921,301,30,722,601,581) THEN 0.50 ELSE 1 END),0),1) *
nvl(nullif(MAX(CASE WHEN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN (2,1, 4) THEN 0.70 ELSE 1 END),0),1) *
nvl(nullif(MIN(CASE WHEN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN (1,2) then 0 else 1 END) *
MAX(CASE WHEN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN (4) then 0.20 else 0 END),0),1) AS "FTE VALUE"
FROM RM_LIVE.EMPBASE,
RM_LIVE.EMPLOYEE,
RM_LIVE.CRWBASE,
RM_LIVE.EMPNAME,
RM_LIVE.CRWSPECFUNC,
RM_LIVE.EMPSPECFUNC,RM_LIVE.EMPQUALCAT,RM_LIVE.CRWCAT
where RM_LIVE.EMPBASE.IDEMPNO = RM_LIVE.EMPLOYEE.IDEMPNO
AND RM_LIVE.EMPBASE.IDCRWBASE = RM_LIVE.CRWBASE.IDCRWBASE
AND RM_LIVE.EMPLOYEE.IDEMPNO = RM_LIVE.EMPNAME.IDEMPNO
AND RM_LIVE.EMPSPECFUNC.IDCRWSPECFUNC =RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC
AND RM_LIVE.EMPSPECFUNC.IDEMPNO =RM_LIVE.EMPLOYEE.IDEMPNO
AND RM_LIVE.EMPQUALCAT.IDEMPNO=RM_LIVE.EMPLOYEE.IDEMPNO
AND RM_LIVE.CRWCAT.IDCRWCAT = RM_LIVE.EMPQUALCAT.IDCRWCAT
AND RM_LIVE.CRWCAT.crwcat IN ('CP','FO','CM','MC')
AND RM_LIVE.CRWBASE.BASE <> 'XYZ'
AND RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN
('921','2' ,'1','301','17','4','3','7','302' ,'861','31',
'723','30','722 ','29 ','721','16','601','581')
AND RM_LIVE.EMPBASE.STARTDATE <= SYSDATE
AND RM_LIVE.EMPBASE.ENDDATE >= SYSDATE
AND RM_LIVE.EMPSPECFUNC.STARTDATE <= SYSDATE
AND RM_LIVE.EMPSPECFUNC.ENDDATE >= SYSDATE
AND RM_LIVE.EMPNAME.FROMDATE <=SYSDATE
AND RM_LIVE.EMPQUALCAT.STARTDATE <= SYSDATE
AND RM_LIVE.EMPQUALCAT.ENDDATE >= SYSDATE
GROUP BY RM_LIVE.EMPLOYEE.EMPNO, RM_LIVE.EMPNAME.FIRSTNAME,
RM_LIVE.EMPNAME.LASTNAME, RM_LIVE.CRWBASE.BASE,RM_LIVE.CRWCAT.crwcat;
According to desired reasult comment, try this
SELECT [id]
,[name]
, r = max(CASE WHEN [code] IN (1,2,4) then 100 else 0 end)
+ max(CASE WHEN [code] IN (8) then 80 else 0 end)
FROM
-- your table here
(values (1, 'ali',4)
,(1, 'ali',1)
,(1, 'ali',8)
) as t(id, name,code)
GROUP BY id, name;
EDIT another story for excluding something.
Any of 1,2,4 give 100 plus if it was only 4 without (1,2) add 400.
SELECT [id]
,[name]
, r = max(CASE WHEN [code] IN (1,2,4) then 100 else 0 end)
+ min(CASE WHEN [code] IN (1,2) then 0 else 1 end)
* max(CASE WHEN [code] IN (4) then 400 else 0 end)
+ max(CASE WHEN [code] IN (8) then 80 else 0 end)
FROM
-- your table here
(values (1, 'ali',4)
,(1, 'ali',1)
,(1, 'ali',8)
,(2, 'ali',4)
,(2, 'ali',8)
) as t(id, name,code)
GROUP BY id, name;
EDIT 2 If you need multiply scores, replace + with * and convert 0 into 1.
SELECT [id]
,[name]
,r = isnull(nullif(
max(CASE WHEN [code] IN (1,2,4) then 100 else 0 end)
,0),1)
* isnull(nullif(
min(CASE WHEN [code] IN (1,2) then 0 else 1 end)
* max(CASE WHEN [code] IN (4) then 400 else 0 end)
,0),1)
* isnull(nullif(
max(CASE WHEN [code] IN (8) then 80 else 0 end)
,0),1)
FROM
-- your table here
(values (1, 'ali',4)
,(1, 'ali',1)
,(1, 'ali',8)
,(2, 'ali',4)
,(2, 'ali',8)
) as t(id, name,code)
GROUP BY id, name;
You missed a comma (,) before the calculating the sum.
So your code should be:
SELECT [id]
,[name]
,SUM(CASE WHEN (SELECT [code]
FROM [Test].[dbo].[testcode] as ts
WHERE ts.id = t.id) IN (1,2,4)
then 100
else 10
end) as "total"
FROM [Test].[dbo].[testcode] as t
GROUP BY id, name
You're already selecting from the testcode table - no need to do any subqueries in your CASE expression - just use this code:
SELECT
[id], [name],
SUM(CASE
WHEN [code] IN (1, 2, 4)
THEN 100
WHEN [code] = 8
THEN 80
END) AS [total]
FROM
[Test].[dbo].[testcode] AS t
GROUP BY
id, name

Use the result from one column to make column names

I have select statement, something like:
select trim(time), type, count(1) from table
group by trim(time),type
The results are:
02.10.13 REZ1 1
02.10.13 REZ2 5
02.10.13 REZ3 3
Is it possible to make some select statement with some Oracle function to get the following result:
REZ1 REZ2 REZ3
1 5 3
So, results from one column are column names in the other statement, something like:
select ?SOMETHING?
from (
select trim(time), type, count(1)
from table
group by trim(time),type) s
WITH t(l_date, val, l_count)
AS
(SELECT to_date('02.10.13', 'dd.mm.yy'), 'REZ1' , 1 FROM dual UNION
SELECT to_date('02.10.13', 'dd.mm.yy'), 'REZ2' , 5 FROM dual UNION
SELECT to_date('02.10.13', 'dd.mm.yy'), 'REZ3' , 3 FROM dual
)
SELECT *
FROM
( SELECT val, l_count FROM t
) PIVOT (MAX(l_count) FOR (val) IN ('REZ1' REZ1,'REZ2' REZ2 ,'REZ3' REZ3));
Perhaps you can try the SQL alternative for this:
SELECT MAX(CASE type
WHEN 'REZ1' THEN cnt
ELSE NULL
END) AS REZ1,
MAX(CASE type
WHEN 'REZ2' THEN cnt
ELSE NULL
END) AS REZ2,
MAX(CASE type
WHEN 'REZ3' THEN cnt
ELSE NULL
END) AS REZ3
FROM (SELECT trim(time), type, count(1) as cnt FROM table
GROUP BY trim(time), type);
Or even better:
SELECT COUNT(CASE type
WHEN 'REZ1' THEN 1
ELSE NULL
END) AS REZ1,
COUNT(CASE type
WHEN 'REZ2' THEN 1
ELSE NULL
END) AS REZ2,
COUNT(CASE type
WHEN 'REZ3' THEN 1
ELSE NULL
END) AS REZ3
FROM table;
OUTPUT:
REZ1 | REZ2 | REZ3
1 | 5 | 3
This is applicable when you know the values in the type column. Even pivot, which is available in 11g, requires you to know the values in the column in order to pivot this as described in ajmalmhd04's answer.
Assuming the 2nd column will not have any value other than REZ1..3 then following solution will transpose the table data and take care of repetition as well by adding up the values.
WITH t
AS (SELECT TO_DATE ('02.10.13', 'dd.mm.yy') AS dt,
'REZ1' AS typ,
1 AS cnt
FROM DUAL
UNION
SELECT TO_DATE ('02.10.13', 'dd.mm.yy') AS dt,
'REZ2' AS typ,
5 AS cnt
FROM DUAL
UNION
SELECT TO_DATE ('02.10.13', 'dd.mm.yy') AS dt,
'REZ3' AS typ,
3 AS cnt
FROM DUAL
UNION
SELECT TO_DATE ('03.10.13', 'dd.mm.yy') AS dt,
'REZ1' AS typ,
7 AS cnt
FROM DUAL
UNION
SELECT TO_DATE ('03.10.13', 'dd.mm.yy') AS dt,
'REZ2' AS typ,
2 AS cnt
FROM DUAL)
SELECT dt,
SUM (CASE WHEN typ = 'REZ1' THEN cnt ELSE 0 END) AS "REZ1",
SUM (CASE WHEN typ = 'REZ2' THEN cnt ELSE 0 END) AS "REZ2",
SUM (CASE WHEN typ = 'REZ3' THEN cnt ELSE 0 END) AS "REZ3"
FROM t
GROUP BY dt;
DT REZ1 REZ2 REZ3
--------- ---------- ---------- ----------
02-OCT-13 1 5 3
03-OCT-13 7 2 0
2 rows selected.
Incase column#2 is going to have random values, probably some kind of cursor needs to use to tweak this query for considering dynamic columns.
I will try to post that if I able to get that designed.
select trim(time),
count(decode(type, 'REZ1', 1)) AS REZ1,
count(decode(type, 'REZ2', 1)) AS REZ2,
count(decode(type, 'REZ3', 1)) AS REZ3
from table
group by trim(time)