Im working with the oracle pdf's to learn pl/sql.
There is an exercise where i have to create a new table with data out
of two other tables already existing. I thought this would do the trick:
CREATE TABLE new_depts
AS SELECT d.department_id, d.department_name, sum(e.salary) dept_sal
FROM employees e, departments d
WHERE e.department_id = d.department_id;
But this raises the following error:
SQL-Fehler: ORA-00937: not a single-group group function
00937. 00000 - "not a single-group group function"
I cant find something usefull about this error. From what i know yet
about SQL my code should work fine!
Am i wrong?
Try adding group by clause :
CREATE TABLE new_depts
AS SELECT d.department_id, d.department_name, sum(e.salary) dept_sal
FROM employees e, departments d
WHERE e.department_id = d.department_id
group by d.department_id,d.department_name
Update 1
You need to use group by clause in your select query because you are using aggregate function: sum(e.salary). If you are using aggregate function then you need to have group by clause. Please see here for more information about group by clause.
The main concept to understanding why aggregate functions or columns that are specified in the GROUP BY clause cannot be mixed with other non aggregate expressions in the select list is the level of detail of the value they produce. The select list of the SELECT statement can include only expressions that produce values that are on the same level of detail as others in that select list.
Example 1: incorrect
SELECT avg(col1) --> level of detail of the value is aggregated
,col2 --> level of detail of the value is only for one row
FROM table_a;
Example 2: correct
SELECT avg(col1) --> level of detail of the value is aggregated
,col2 --> level of detail of the value is aggregated
FROM table_a
GROUP BY col2;
By including a column in the GROUP BY clause you aggregate the specified column and change its level of detail from single row to aggregate.
Related
I have this sqlite database:
And I need to get the set from AssignmentMetric for a certain Athlete_id AND for Assignments which include a skill with Value X.
I've looked all over JOIN, LEFT JOIN but cannot find any examples that seems to match exactly this. I can query to get Assignment metrics for a particular Athlete ID And Assignment ID, but I am trying to narrow the Assignments to ones that are for a specific skill "of X value". How do I "reach through" the Assignment table to grab the value from the Skill table?
You could do:
SELECT ...
FROM
AssignmentMetric
INNER JOIN Assignment
ON AssignmentMetric.Assignment_id =
Assignment.Assignment_id
INNER JOIN
Skill
ON Skill.Skill_id = Assignment.Skill_id
WHERE ...
In the WHERE you can refer to the colums of the tables using the tablename.columnname notation.
Can someone please explain me, what is the difference between qualify...over...partition by and group by...having in Teradata?I would also like to know if there are any differences in their performances.
QUALIFY is a proprietary extension to filter the result of a Windowed Aggregate Function.
A query is logically processed in a specific order:
FROM: create the basic result set
WHERE: remove rows from the previous result set
GROUP BY: apply aggregate functions on the previous result set
HAVING: remove rows from the previous result set
OVER: apply windowed aggregate functions on the previous result set
QUALIFY: remove rows from the previous result set
Having clause is used to filter the result set of the aggregate functions like (COUNT,min,max etc)
they eliminate rows based from groups based on some criteria like this :-
SELECT dept_no, MIN(salary), MAX(salary), AVG(salary)
FROM employee
WHERE dept_no IN (100,300,500,600)
GROUP BY dept_no
HAVING AVG(salary) > 37000;
The QUALIFY clause eliminates rows based on the function value, returning a new value for each of the participating rows.
It works on the final result set.
SELECT NAME,LOCATION FROM EMPLOYEE
QUALIFY ROW_NUMBER() OVER ( PARTITION BY NAME ORDER BY JOINING_DATE DESC) = 1;
We can club both having and qualify as well in a query if we use both aggregate and analytical fucntion like below:-
SELECT StoreID, SUM(sale),
SUM(profit) OVER (PARTITION BY StoreID)
FROM facts
GROUP BY StoreID, sale, profit
HAVING SUM(sale) > 15
QUALIFY SUM(profit) OVER (PARTITION BY StoreID) > 2;
You can see there order of execution from dnoeth answer.
This is a pretty simple question that I haven't been able to find an answer for. Is it possible to have two separate SELECT commands (from the same table) in the same SqlDataSource command to populate two different cells in a given GridView?
I haven't been able to find current information so far.
::EDIT::
The challenge is that I'm attempting to manupulate one cell with a COUNT command and the second cell with a numerical grand total from the same information.
You can Combine results from two separate SELECT Statements by doing something like this..
SELECT X.A , Y.B
FROM (SELECT Column1 AS A FROM TableName) X, (SELECT Column2 AS B FROM TableName) Y
I'm curious if there is a workaround for excluding a field in the 'group by' statement in Hive?
select g.country, count(*) as road_count
from geography g
join g_street gs on (g.id=gs.id)
group by g.iso_country_code, g.virtual
having (g.virtual='f' or g.virtual is null)
;
I do not want the 'g.virtual' in the group by statement because my result should be grouped by country only. Hive requires the 'g.virtual' in the group by statement.
Thanks in advance!
I am not sure about what you are trying to achieve with the query. Since I see fields in select which don't appear in the group by statement. The only suggestion that I can give is if you plan to put a restriction on geography table then you can place a where clause before joining it with g_street and then group by on the required fields.
Here is an example :
select g.iso_country_code, count(*)
from geography g
where g.virtual='f' or g.virtual is null
join g_street gs on (g.id=gs.id)
group_by g.iso_country_code
I have two tables, one contains a list of items which is called watch_list with some important attributes and the other is just a list of prices which is called price_history. What I would like to do is group together 10 of the lowest prices into a single column with a group_concat operation and then create a row with item attributes from watch_list along with the 10 lowest prices for each item in watch_list. First I tried joins but then I realized that the operations where happening in the wrong order so there was no way I could get the desired result with a join operation. Then I tried the obvious thing and just queried the price_history for every row in the watch_list and just glued everything together in the host environment which worked but seemed very inefficient. Now I have the following query which looks like it should work but it's not giving me the results that I want. I would like to know what is wrong with the following statement:
select w.asin,w.title,
(select group_concat(lowest_used_price) from price_history as p
where p.asin=w.asin limit 10)
as lowest_used
from watch_list as w
Basically I want the limit operation to happen before group_concat does anything but I can't think of a sql statement that will do that.
Figured it out, as somebody once said "All problems in computer science can be solved by another level of indirection." and in this case an extra select subquery did the trick:
select w.asin,w.title,
(select group_concat(lowest_used_price)
from (select lowest_used_price from price_history as p
where p.asin=w.asin limit 10)) as lowest_used
from watch_list as w