I've figured out CUBE as just generating all the permutations, but I am having trouble with ROLLUP. There don't seem to be any good resources online or in the book I'm reading for explaining SQL for people like me who struggle with it.
My book says that ROLLUP is a special case of the CUBE operator that excludes all cases that don't follow a hierarchy within the results.
I'm not entirely sure what it means, but running it on a table I made kinda produces some useful results.
I made a table from another page on google like this:
Type Store Number
Dog Miami 12
Cat Miami 18
Turtle Tampa 4
Dog Tampa 14
Cat Naples 9
Dog Naples 5
Turtle Naples 1
Then here is query I made:
select store,[type], SUM(number) as Number from pets
group by store, [type]
with rollup
This shows me the number of each type of pet in each store, and total pets in each store, which is kinda cool. If I want to see the query based on pets, I found I have to switch the group by order around so type comes first.
So is rollup based on the first group by clause?
The other question is, I read you use ROLLUP instead of CUBE when you have a year and month column to stop it aggregating the same month across multiple years. I think I understand what this means, but could anyone clarify it? And how do you set it up like this?
Can you use ROLLUP to exclude other combinations of columns as well? My table above is quite simple and the query shows you "pets by store", but if there were other columns, could you include/exclude them from the results?
Best explained through an example. Suppose you group by A, B, C. You then get the following groupings with rollup:
(A, B, C)
(A, B)
(A)
()
So you see that the order is important, as you already found out. If you group by A, C, B, you get the following groupings instead:
(A, C, B)
(A, C)
(A)
()
SELECT departments.department_name
FROM departments
LEFT OUTER JOIN job_history
ON departments.department_id = job_history.department_id
WHERE job_history.employee_id IS NULL;
ex.3
SELECT department_id, manager_id, COUNT() as Numar
FROM Employees
GROUP BY ROLLUP(department_id, manager_id)
UNION
SELECT department_id, manager_id, COUNT() as Numar
FROM Employees
GROUP BY ROLLUP(manager_id, department_id);
SELECT department_id, manager_id, COUNT(employee_id) as employee_count
FROM employee
GROUP BY ROLLUP (department_id, manager_id);
SELECT employee_id, first_name, manager_id
FROM employee
START WITH employee_id = :employee_id
CONNECT BY PRIOR employee_id = manager_id;
ex3.1SELECT department_id, manager_id, COUNT() as Numar
FROM Employees
GROUP BY ROLLUP(department_id, manager_id)
UNION
SELECT department_id, manager_id, COUNT() as Numar
FROM Employees
GROUP BY ROLLUP(manager_id, department_id);
Related
i've just study SQL for a month and there is many things I'm still cannot get a hold of. Can anyone help me, plz provide the results with some explaination, I need to understand it for future uses. I only list things that I cannot understand.
List the ID of the managers and the total number of employees reporting to each of them. Display the result in descending order of the total number of employees
I can do:
SELECT employeeNumber
FROM employees
WHERE jobTitle LIKE '%Manager%'
UNION
SELECT employeeNumber, COUNT(*)
FROM employees
WHERE reportsTo 'WHICH CONDITION?'
ORDER BY COUNT(*) DESC
Can someone fill in after 'reportTo', I cant find a condition that's working TYT
Display all offices and their counts in each country
I think this mean showing a table with every country and count total number of offices in that country
I can do:
SELECT country, COUNT(*)
FROM offices
GROUP BY country
UNION
SELECT country, officeCode
FROM offices
But the results is not as expected
select
reportsTo,
COUNT(employeeNumber) as numberOfEmployees
from employees
group by reportsTo
Will give you a count of employeeNumbers that report to that reportsTo.
This will not give you the managers where nobody is reporting to, so to do that you would have to make a JOIN:
SELECT
a.employeeNumber AS managerNumber,
COUNT(b.employeeNumber) AS numberOfEmployees
FROM employees AS a
LEFT JOIN employees AS b on (b.reportsTo=a.employeeNumber)
WHERE a.jobTitle LIKE '%Manager%'
GROUP BY a.employeeNumber
I want to display the name of the departments that has the least student count. This is my query:
select department_name, count(student_id)
from department d, student s
where d.department_id = s.department_id
group by department_name;
This query works fine and shows student count, but when I add the min function as min(count(student_id)), it fails with:
ERROR at line 1: ORA-00937: not a single-group group function
I don't know what I am doing wrong. Any help/suggestion?
As others have noted, when you wrapped the count in MIN that would have been getting the min PER DEPARTMENT. Because there is already only one row per department, this is a non-operation
What you say you want is a min over ALL DEPARTMENTS. Something like this:
Select department_name from(
select department_name, count(student_id), rank() over(order by count(student_id)) as x
from department d, student s
where d.department_id = s.department_id
group by department_name
)
Where x = 1
How it works? The rank() function assigns a position to rows in order, like winning a race. In this case the order is ascending count() of students, hence the minimum count is in position 1. What is special with rank is that rows with equal counts have an equal rank. We thus know that all rows that are ranked 1 are all equally the minimum count. To show only rows that are =1 we have to use a subquery, alas (I know you didn't want to see it) because oracle doesn't let us say something like where rank() over(...) =1. The subquery isn't really a performance penalty though, because the ranking is prepared at the same time as the rest of the data is single scanned, and then this passes through the filter of the outer where clause. This is different to the other posted answer that uses HAVING.. in that case the query is run, all the counts are found, the min of them all is found, then the query is run again, the counts are found again, and then the HAVING filters them down to the min that was found before
In this case, MIN() function works before GROUP BY function. So error came. You can try this.
SELECT TOP 1 department_name,count(student_id) as A
FROM department d,student s
WHERE d.department_id=s.department_id
GROUP BY department_name
ORDER BY A DESC
If I understand correctly, you need to find the department that has least number of students. Below query can give you the answer.
select department_name
from department d, student s
where d.department_id = s.department_id
group by department_name
having count(student_id) = (select min(a.cnt_std_id) from (select
department_name, count(student_id) cnt_std_id
from department d, student s
where d.department_id = s.department_id
group by department_name)a);
Here's another way:
select department_name, students
from ( select department_name, count(*) as students
, rank() over (order by count(*)) as seq
from department join student using(department_id)
group by department_name )
where seq = 1;
It is an easy way. Goodluck
SELECT department_name, MIN(A)
FROM (select department_name, count(student_id) as A
from department d, student s
where d.department_id = s.department_id
group by department_name)
I have a query which uses MULTIPLE tables and joins. It returns a list of items. I need to count how many times each item appears in that list. I'm working on Oracle database using SQL Developer.
Use GROUP, example:
select COUNT(employee_id), department_id
from employee
GROUP BY department_id
ORDER BY department_id;
Result:
COUNT(EMPLOYEE_ID) DEPARTMENT_ID
—————————————————— —————————————
6 10
2 20
2 30
1
Do you mean like this one?
Select COUNT(e.employee_id), d.dept_name
from employee e
inner department d
on d.id = e.dept_id
GROUP BY d.dept_name
I would like to see your query to understand better your issue and find an accurate solution, but if you use the count function like this, you have the list of repeated elements with a counter column:
SELECT COUNT(*) AS "Quantity", l1.attrib, l2.attrib
FROM list1 l1, list2 l2
WHERE l1.attrib = l2.attrib
GROUP BY l1.attrib, l2.attrib;
The limit of shown data could be the GROUP BY clause and the amount of fields with different data you want to see.
Can you please help me with a query that would display a table like this:
Dept_ID Dept_Name
10 Admin
10 Whalen
20 Sales
20 James
20 King
20 Smith
40 Marketing
40 Neena
and so on...The Schema is HR
Display the Department Id and the Department Name and then the subsequent employees last names working under that department
SELECT Dept_ID, Dept_Name
FROM Your_Table
Simple as I can make it. It's very difficult (near impossible) to tell exactly what the query should be without more detail in terms of your table structure and some sample data.
From your edit, you may need something more like this;
SELECT DT.Dept_ID, DT.Dept_Name, ET.Emp_Name
FROM Dept_Table AS DT INNER JOIN Emp_Table AS ET ON DT.Dept_ID = ET.Dept_ID
ORDER BY Dept_ID
This shows the employees in each department on the next column, you don't really want all that in the same column.
When you union two data sets, there is NO implicit ordering, you could get the results in any order.
The get a particular order you must use ORDER BY.
To use ORDER BY, then you must have fields to do that ordering by.
In your case, the pseudo code would be...
- ORDER BY [dept_id], [depts-then-employees], [dept_name]
The middle of those three is something that YOU are going to have to create.
One way of doing that is as follows.
note: Just because you have a field to order by, does not mean that you have to select it.
SELECT
dept_id,
dept_name
FROM
(
SELECT
d.dept_id,
d.dept_name,
0 AS entity_type_ordinal
FROM
department d
UNION ALL
SELECT
d.dept_id,
e.employee_name,
1 AS entity_type_ordinal
FROM
department d
INNER JOIN
employee e
ON e.dept_id = d.dept_id
)
dept_and_emp
ORDER BY
dept_id,
entity_type_ordinal,
dept_name
Assuming there's a table in your database called departments that holds this information, your code might look like this:
select
dept_id, dept_name
from
departments
If you want to display certain columns of the table like you have asked in the question above , you can use the following syntax :
select column_names from table_name
replace:
column_names with the column names you want to display separated by a coma
2.table_name with the name of the table whose columns you wish to display
for the above question , the following code will do:
select Dept_Id , Dept_Name from Department ;
The above code works if your table name is 'Department'
I have tables which looks like below.
Employee table
Date Employee ID Employer ID Salary
2/3/2011 10 20 45666
3/12/2009 43 53 2356
Employer Table
Employer ID State
53 OH
42 MI
Trying to get the total salary by month and by state using group by clause. But not getting the results. what am i doing wrong?? any help appreciated
select date, sum(salary) from employee
group by to_char(date,'MON')
select sum(salary) from employee A, Employer B
where A.employer id=B.employer id
group by B.state
Also i need to get the top 10 distinct employee ids based on their salary
select DISTINCT employee id from employee
where rownum<=10
order by salary desc
You have to group by the exact expression in your select list, e.g.,
select to_char(date,'MON'), sum(salary)
from employee
group by to_char(date,'MON');
You probably want to include the state in your second query:
select b.state, sum(salary)
from employee A, Employer B
where A.employer_id=B.employer_id
group by B.state;
Generally speaking, stating in your question that you're "not getting the results" is not very helpful to the folks you're asking help of. Please provide any error messages or output that describes what "not getting the results" means.