Oracle SQL- Getting "Distinct" values within a "CASE" query - sql

I have the following query in ORACLE SQL:
Select
Trunc(Cs.Create_Dtime),
Count(Case When Cs.Cs_Listing_Id Like '99999999%' Then (Cs.Player_Id) End) As Sp_Dau,
Count(Case When Cs.Cs_Listing_Id Not Like '99999999%' Then (Cs.Player_Id) End) As Cs_Dau
From
Player_Chkin_Cs Cs
Where
Trunc(Cs.Create_Dtime) >= To_Date('2012-Jan-01','yyyy-mon-dd')
Group By Trunc(Cs.Create_Dtime)
Order By 1 ASC
I added "Distinct" just before "case" for each count. I just want to make sure that this only returns all of the distinct player_Ids in each case. Can some one confirm? Thank you! Here is the final query:
Select
Trunc(Cs.Create_Dtime),
Count(Distinct Case When Cs.Cs_Listing_Id Like '99999999%' Then (Cs.Player_Id) End) As Sp_Dau,
Count(Distinct Case When Cs.Cs_Listing_Id Not Like '99999999%' Then (Cs.Player_Id) End) As Cs_Dau
From
Player_Chkin_Cs Cs
Where
Trunc(Cs.Create_Dtime) >= To_Date('2012-Jan-01','yyyy-mon-dd')
Group By Trunc(Cs.Create_Dtime)
Order By 1 ASC;

A simple test case for you to prove count(distinct ... returns only distinct values:
11:34:09 HR#vm_xe> select department_id, count(*) from employees group by department_id order by 2 desc;
DEPARTMENT_ID COUNT(*)
------------- ----------
50 45
80 34
100 6
30 6
60 5
90 3
20 2
110 2
40 1
10 1
1
70 1
12 rows selected.
Elapsed: 00:00:00.03
11:34:12 HR#vm_xe> select count(department_id) "ALL", count(distinct department_id) "DISTINCT" from employees;
ALL DISTINCT
---------- ----------
106 11
1 row selected.
Elapsed: 00:00:00.02
11:34:20 HR#vm_xe>

Related

Sum SQL rows on every nth and group

My data is as follows:
QUARTER_CMT DEPT SALES
7 A 39
8 A 23
9 A 33
10 A 45
11 A 50
12 A 110
1 B 44
2 B 56
3 B 87
4 B 22
I am aiming at getting total SALES for every 4 quarters by DEPT and retain Quarter_CNT number as a rollup.
QUARTER_CMT DEPT SALES_TOT
7 A 140
11 A 160
1 B 209
Work in progress code. I thought to sub-group totals and join to latest QUARTER_CMT to have one row by DEPT :
SELECT
ROW_NUMBER() OVER(PARTITION BY DEPTORDER BY QUARTER_CMT) as RN,
QUARTER_CMT,
DEPT,
--RANK() OVER(PARTITION BY ODDZIAL ORDER BY QUARTER_COUNT) AS RowNumberRankOrg,
--NTILE(4) OVER(PARTITION BY ODDZIAL ORDER BY QUARTER_COUNT) AS RowNumberRank,
SALES
FROM TABLE_1
ORDER BY DEPT, QUARTER_CMT
Try this:
with a as (
select
row_number() over(partition by dept order by quarter_cmt)-1 n,
quarter_cmt, dept, sales
from t
order by dept, quarter_cmt
)
select min(quarter_cmt) quarter_cmt, dept, sum(sales) sales_tot
from a
group by dept, floor(n/4)
order by dept, quarter_cmt
;
Assuming this sample data:
create or replace table t as
select $1 QUARTER_CMT, $2 DEPT, $3 SALES from values
(7,'A',39),
(8,'A',23),
(9,'A',33),
(10,'A',45),
(11,'A',50),
(12,'A',110),
(1,'B',44),
(2,'B',56),
(3,'B',87),
(4,'B',22)
;
you need to divide row_number to 5 for determine the periods
SELECT MIN (QUARTER_CMT) QUARTER_CMT, DEPT, SUM(SALES) SALES, PART
FROM (
SELECT *, FLOOR(ROW_NUMBER() OVER(PARTITION BY DEPT ORDER BY QUARTER_CMT) / 5) AS PART
FROM TABLE_1
) AS T
GROUP BY DEPT, PART
ORDER BY DEPT, PART
Result:
QUARTER_CMT DEPT SALES PART
----------- ---- ----------- -----------
7 A 140 0
11 A 160 1
1 B 209 0

how to transpose rows to columns for the grouped data?

While doing the employees and supervisors analysis, I got in trouble with the BigQuery statements.
SELECT SupervisorName, Emp_Status, COUNT(DISTINCT EmpNO)AS NUMBER
FROM
(SELECT
EmpNO,
EmpName,
(CASE WHEN TerminationDate IS NULL THEN 'Active'
ELSE 'Terminated'
END
)AS Emp_Status,
DateOfBirth,
DATE_DIFF(CURRENT_DATE(),DateOfBirth,YEAR) AS Age,
SupervisorName
FROM `Table1`
)
GROUP BY SupervisorName, Emp_Status
ORDER BY SupervisorName, NUMBER DESC
The result is shown below:
Row SupervisorName Emp_Status NUMBER
1 null Terminated 321
2 null Active 2
3 Ahearn Active 3
4 Ahearn Terminated 2
5 Allen Active 6
6 Allen Terminated 3
......
How can I change it to like this:
Row SupervisorName Active Termination Total
1 Null 2 321 323
2 Ahearn 3 2 5
3 Allen 6 3 9
......
The standard pattern here is to use SUM and CASE to get the result -- as below:
SELECT
SupervisorName,
SUM(CASE WHEN Emp_Status = 'Active' THEN 1 ELSE 0 END) AS Active,
SUM(CASE WHEN Emp_Status = 'Terminated' THEN 1 ELSE 0 END) AS Termination,
COUNT(*) AS Total
FROM (
SELECT
EmpNO,
EmpName,
CASE WHEN TerminationDate IS NULL THEN 'Active' ELSE 'Terminated' END AS Emp_Status,
DateOfBirth,
DATE_DIFF(CURRENT_DATE(),DateOfBirth,YEAR) AS Age,
SupervisorName
FROM `Table1`
)
GROUP BY SupervisorName
Note, I left the same sub-query you had, but as given you don't actually need a sub-query, you can just change the CASE statement to look at termination date instead of the string you created in the sub-query.
I assume your actual code is more complicated so I left it like this.
maybe that's what you want
select
SupervisorName,
count(distinct if(TerminationDate is null, EmpNO, null)) as active,
count(distinct if(TerminationDate is null, null, EmpNO)) as terminated,
count(distinct EmpNO) as dist_total,
count(*) as total
from
`Table1`
where
-- you should use keyword "date" and iso8601 format
LastHireDate between date'2018-01-01'
and current_date()
group by
1
order by
1, 4 desc

How to get eid from table which is having max number of count in the Mid?

I have a table employee which is having following structure:
Id. Mid Salary
1 20 200
2 20 3000
3 30 200
4 34 4000
5 30 300
6 30 400
1 23 440
1 24 333
2 21 3
I want to get result like:
Id Mid
1 3
You can try below - using top with ties and aggregation
select top 1 with ties id, count(mid) as Mid
from table
group by id
order by count(mid) desc
use top 1
select top 1 id,count(*) as cnt
from table
group by id
order by cnt desc
if you need ties then use with ties
select top 1 with ties id,count(*) as cnt
from table
group by id
order by cnt desc

SQL 2008 Using Top Avg an top row field

With the results of Loc_1 query below, I would like to include the top row balance field 100.
select AVG(Age) as AvgAge , Balance as BalanceLeft from
(
select top(5)* from Employee
where LocationID=1
order by HireDate desc
) as Loc_1
Age HireDate LocationID Balance
30 10-12-2014 1 100
20 09-12-2014 1 200
40 08-12-2014 1 300
50 07-12-2014 1 400
20 06-12-2014 1 500
Results
AvgAge Balanceleft
32 100
i just want to include just the top row column balance i.e 100
You can use conditional aggregation, if I understand the question correctly:
select AVG(Age) as AvgAge,
max(case when seqnum = 1 then Balance end) as BalanceLeft
from (select top(5) e.*,
row_number() over (order by hiredate desc) as seqnum
from Employee e
where LocationID=1
order by HireDate desc
) Loc_1

SELECT employees with count of finished tasks

How would do the following in SQL:
"select all emps with list mark all one's tasks".................................
EmpId EmpName
------ --------
1 tom
2 jerry
3 jack
taskId EmpID mark
------ ----- ------
1 1 5
2 3 0
3 1 10
4 2 5
5 2 10
6 3 5
7 3 5
Result:
EmpName 0 5 10 sum
------ ----- ------ ------ ----
tom 0 1 1 2
jerry 0 1 1 2
jack 1 2 0 3
Try this:
SELECT e.EmpId, e.EmpName,
SUM(CASE WHEN t.mark = 0 THEN 1 ELSE 0 END) AS 0Mark,
SUM(CASE WHEN t.mark = 5 THEN 1 ELSE 0 END) AS 5Mark,
SUM(CASE WHEN t.mark = 10 THEN 1 ELSE 0 END) AS 10Mark,
COUNT(1) AS TotalMark
FROM employee e
INNER JOIN task t ON e.EmpId = t.EmpId
GROUP BY e.EmpId, e.EmpName;
select
e.empname,
(select count(*) from tasks t where e.empid=t.empid and mark=0) as mark0,
(select count(*) from tasks t where e.empid=t.empid and mark=5) as mark5,
(select count(*) from tasks t where e.empid=t.empid and mark=10) as mark10,
(select count(*) from tasks t where e.empid=t.empid) as marksum
from
employees e
It depends on your database engine - google "Pivot SQL " + your database engine (e.g. "pivot SQL MySQL").
The pivot feature means that you can convert values in the "mark" column to column headers, so if you have marks ranging from 0 to 100, you get one column for each value without having to create a subquery.
If your database engine doesn't support pivot, you may need to hard-code the columns in your resultset as #LajosVeres shows. I would add a "catch-all" subquery so if your data changes, you don't get illogical results, like so:
select
e.empname,
(select count(*) from tasks t where e.empid=t.empid and mark=0) as mark0,
(select count(*) from tasks t where e.empid=t.empid and mark=5) as mark5,
(select count(*) from tasks t where e.empid=t.empid and mark=10) as mark10,
(select count(*) from tasks t where e.empid=t.empid and mark not in (0, 5, 10)) as otherMarks,
(select count(*) from tasks t where e.empid=t.empid) as marksum
from
employees e