Grouping Minus Oracle Problems - sql

I've just created this query and I get confuse by the time I grouping this because I can't see them as one grouping. This query runs but not the way I wanted, I want to group the query by the team name but the problem occurs when its query being counted using count(*) and the result of its counting produces the same number ,,,
SELECT TEAM.NAMATEAM, PERSONAL.KODEPERSON
FROM TEAM, PERSONAL
WHERE TEAM.KODETEAM = PERSONAL.KODETEAM
GROUP BY PERSONAL.KODEPERSON, TEAM.NAMATEAM
MINUS
SELECT TEAM.NAMATEAM, PERSONAL.KODEPERSON
FROM TEAM, PERSONAL, AWARD_PERSON
WHERE TEAM.KODETEAM = PERSONAL.KODETEAM
AND AWARD_PERSON.PEMENANG = PERSONAL.KODEPERSON
GROUP BY TEAM.NAMATEAM, PERSONAL.KODEPERSON;
I want to group all these using the team name but using counting will be problem since I have no idea to group within the technique that can be run smoothly as I wanted. Thank you.

Do I understand your question? You are trying to make a table of columns NAMATEAM,X where NAMATEAM are the team names, and X are the number of people on each team who do not have awards (listed in AWARD_PERSON). If so, you should be able to use a sub-select:
SELECT T_NAME, COUNT(*)
FROM (
SELECT TEAM.NAMATEAM "T_NAME", PERSONAL.KODEPERSON
FROM TEAM, PERSONAL
WHERE TEAM.KODETEAM = PERSONAL.KODETEAM
MINUS
SELECT TEAM.NAMATEAM "T_NAME", PERSONAL.KODEPERSON
FROM TEAM, PERSONAL, AWARD_PERSON
WHERE TEAM.KODETEAM = PERSONAL.KODETEAM
AND AWARD_PERSON.PEMENANG = PERSONAL.KODEPERSON )
-- your original query without the GROUP BYs
GROUP BY T_NAME
The first subselect SELECT creates a full list of players, the second subselect SELECT creates a list of players who have won awards (I assume), the MINUS removes the award winners from the full list. Thus the full subselect returns a list of players and their teams, for all players without awards.
The main SELECT then summarizes on the team name only, to yield a per-team count of players without awards.
You should not need your original GROUP BY TEAM.NAMATEAM, PERSONAL.KODEPERSON, unless you have duplicate rows in your database, e.g., one player on one team has more than one row in the database.

Related

COUNT(*) function is returning multiple values

I am writing a specific sql query that needs to return the position of a particular entry, based on a grouped table.
Background info: I am coding a Golf Club Data Management system using Java and MS Access. In this system, the user is able to store their scores as a new entry into this table. Using this table, I have managed to extract a ranking of the top 3 Golf players, using all their recorded scores (I only used top 3 to preserve screen space).
Select TOP 3 Username, Sum(Points)
FROM Scores
GROUP By Username
ORDER BY Sum(Points) desc
This produces the required result. However, if the current user falls outside of the top 3, I want to be able to tell the user where they currently sit in the complete ranking of all the players. So, I tried to write a query that counts the number of players having a sum of points below the current user. Here is my query:
Select COUNT(*)
From Scores
GROUP BY Username
HAVING Sum(Points) < (Select Sum(Points)
FROM Scores
WHERE Username = 'Golfer210'
GROUP By Username)
This does not produce the expected number 2, but instead does this.
I have tried removing the GROUP BY function but that returns null. The COUNT DISTINCT Function refuses to work as well, and continuously returns a syntax error message, no matter how I word it.
Questions: Is there a way to count the number of entries while using a GROUP BY function? if not, is there an easier, more practical way to select the position of an entry from the grouped table? Or can this only be done in Java, after the ranking has been extracted from the database? I have not been able to find a solution anywhere
You need an additional level of aggregation:
SELECT COUNT(*)
FROM (SELECT COUNT(*)
FROM Scores
GROUP BY Username
HAVING Sum(Points) < (SELECT Sum(Points)
FROM Scores
WHERE Username = 'Golfer210'
)
) as s;
Note: You might want to check if your logic does what you expect when there are ties.

SQL - Distinct Not Providing Unique Results for Designated Column

I'm currently learning SQL by working through these exercises: https://sqlzoo.net/wiki/The_JOIN_operation
I'm on Example 8 which asks: "Show the name of all players who scored a goal against Germany."
Here is what I currently have:
SELECT DISTINCT(goal.player), goal.gtime, game.team1, game.team2
FROM game JOIN goal ON (goal.matchid = game.id)
WHERE (game.team1='GER' OR game.team2='GER') AND (goal.teamid<>'GER')
I would expect that results would be returned with only unique names. However, that is not the case as we can see "Mario Balotelli" is listed twice. Why doesn't the DISTINCT command work in this instance?
Thank you!
DISTINCT operates on the record level, so you should use distinct for the whole row or if you need extra fields to show up in your result, you need to perform a GROUP BY on the player and bring along other fields by joining to the grouped result.
but i reckon the intended answer is only the player name, so query would be something like this:
SELECT DISTINCT player
FROM game JOIN goal ON matchid = id
WHERE (game.team1='GER' OR game.team2='GER') AND (goal.teamid<>'GER')
It looks like "Mario Balotelli" can have multiple goal.gtime. Or can have different contributing values from Team1 and Team2. So try removing the additional columns you have in your select clause.
DISTINCT gets the distinct rows based on all selected columns. As the goal times differ selecting that column will make the rows different (distinct) from one another.
The question only asks you to select the player's name
SELECT DISTINCT player
FROM game
JOIN goal ON matchid = id
WHERE (team1='GER' OR team2='GER')
AND (teamid <>'GER')
This link looks like it would useful further reading https://www.designcise.com/web/tutorial/what-is-the-order-of-execution-of-an-sql-query
Edit: If you want more than one column but only a distinct list of players you are in the realms of aggregation, you would min/max/sum/avg the other data for the group.
SELECT player, team1, team2, MIN(gtime) AS min_gtime, MAX(gtime) AS max_gtime, COUNT(1) AS goals_scored
FROM game
JOIN goal ON matchid = id
WHERE (team1='GER' OR team2='GER')
AND (teamid <>'GER')
GROUP BY player, team1, team2

SQL Join query brings multiple results

I have 2 tables. One lists all the goals scored in the English Premier League and who scored it and the other, the squad numbers of each player in the league.
I want to do a join so that the table sums the total number of goals by player name, and then looks up the squad number of that player.
Table A [goal_scorer]
[]1
Table B [squads]
[]2
I have the SQL query below:
SELECT goal_scorer.*,sum(goal_scorer.number),squads.squad_number
FROM goal_scorer
Inner join squads on goal_scorer.name=squads.player
group by goal_scorer.name
The issue I have is that in the result, the sum of 'number' is too high and seems to include duplicate rows. For example, Aaron Lennon has scored 33 times, not 264 as shown below.
Maybe you want something like this?
SELECT goal_scorer.*, s.total, squads.squad_number
FROM goal_scorer
LEFT JOIN (
SELECT name, sum(number) as total
FROM goal_scorer
GROUP BY name
) s on s.name = goal_scorer.name
JOIN squads on goal_scorer.name=squads.player
There are other ways to do it, but here I'm using a sub-query to get the total by player. NB: Most modern SQL platforms support windowing functions to do this too.
Also, probably don't need the left on the sub-query (since we know there will always be at least one name), but I put it in case your actual use case is more complicated.
Can you try this if you are using sql-server?
select *
from squads
outer apply(
selecr sum(goal_scorer.number) as score
from goal_scorer where goal_scorer.name=squads.player
)x

Why use many columns in GROUP BY and HAVING clause in these examples

Given the schema here I'm trying to understand and solve the below 3 sql queries as I'm confused:
1- Present a table giving the names of the countries with ≥ 50% urbanization
rates, their urbanization rates, and their per capita GDP. Note that
urbanization rate is the percentage of population living in cities. Do not
count cities with NULL values for population.
SELECT country.name, round(sum(city.population)/country.population, 3) AS urban, round(gdp/country.population, 3) AS gdppc
FROM city
INNER JOIN country ON code = country
INNER JOIN economy ON code = economy.country
WHERE city.population IS NOT NULL
GROUP BY country.name, country.population, economy.gdp
HAVING round(sum(city.population)/country.population, 3) >= 0.5
ORDER BY urban DESC;
In the above query, Why I need to include country.population and economy.gdp in the GROUP BY? If I tried using just country.name in the GROUP BY I get an error saying I should include the others.
2- Show organizations that have as members all the European countries with over 50 million people?
SELECT name
FROM organization
INNER JOIN (SELECT organization
FROM country
INNER JOIN encompasses
ON code = encompasses.country
INNER JOIN ismember
ON code = ismember.country
WHERE population > 50000000 AND continent = 'Europe'
GROUP BY organization
HAVING count(ismember.country) = (SELECT count(*)
FROM country
INNER JOIN encompasses
ON code = country
WHERE population > 50000000 AND continent = 'Europe'))
AS innerQuery
ON abbreviation = innerQuery.organization;
Why I need the HAVING Part above?
3- Insert a new organization called “Tivoli” and a trigger that says if Germany joins “Tivoli” then so too must the UK and France. Insert Germany into the “Tivoli” organization. Confirm proper behavior.
I tried the below script but it's not working, any advice please?
do $$
begin
IF(NOT EXISTS ( SELECT 1 FROM organization WHERE organization."name" = 'Tivoli' AND organization.country = 'D' ))
BEGIN
INSERT INTO organization VALUES ('Tivoli','Tivoli organization',NULL,'F',NULL,NULL);
INSERT INTO organization VALUES ('Tivoli','Tivoli organization',NULL,'GB',NULL,NULL);
END;
end $$
1)
You used country.population and economy.gdp in the select, outside of aggregate functions ( COUNT(), AVG() and SUM() ), and you have a GROUP BY. Everything that you select has to be in GROUP BY or inside of aggregate functions.
2)
Because you were asked to show organizations that have ALL of 50mil + people countries. With HAVING, you check if that organization has the right amount of countries.
3)
organization."name" = 'Tivoli'
It's supposed to be :
organization.name
First of all, you should limit a question to one only, not 3. But here are some pointers for all 3:
In the above query, Why I need to include country.population and economy.gdp in the GROUP BY? If I tried using just country.name in the GROUP BY I get an error saying I should include the others.
This is a requirement. A group by country.name alone would work (in Postgres 9.1+) only if the other two fields are known to be functionally dependent on country.name. But probably country.name is not the primary key of the country table, so in theory it is possible to have two records in that table with the same name, but different population.
The rule is as follows:
When GROUP BY is present, it is not valid for the SELECT list expressions to refer to ungrouped columns except within aggregate functions or if the ungrouped column is functionally dependent on the grouped columns, since there would otherwise be more than one possible value to return for an ungrouped column. A functional dependency exists if the grouped columns (or a subset thereof) are the primary key of the table containing the ungrouped column.
This is implemented since version 9.1.
Why I need the HAVING Part above?
Because a condition on an aggregate (count in this case) can only be performed after grouping, and can thus not be expressed in the where clause. In this case the having clause makes sure that the organisation is not only present in some big EU Member States, but all big EU Member states.
I tried the below script but it's not working, any advice please?
Without a proper database schema, it is not possible to provide you with the correct SQ, but from the ERD diagram it seems that the organization table does not have a country field. Instead the ismember table connects organizations with countries. You would only insert one organization, but several ismember records (one per Member State involved)
It is better also to name the fields in your insert statement, so it is clear which value corresponds to which field.

Return all entries in groups where a group member satisfies condition x

In Ms Access, I'm trying to write a SQL query that answers a question like:
Return all player IDs on all teams in a list of football players where at least one member of the team is injured.
I'm new to SQL. I've tried something like
SELECT pid FROM players WHERE team_id IN
(SELECT team_id FROM players WHERE injury = 'yes')
Access won't accept this IN. Is there a simple way to do this? I'd rather run thus as one query, instead of creating separate queries, so I can change it easily as necessary.
I find it hard to believe that it doesn't support IN, nevertheless you can do it using a join:
SELECT distinct players.pid
FROM players as injured
INNER JOIN players on players.team_id = injured.team_id
WHERE injured.injury = 'yes'
I used distinct in case there's multiple injured players on the one team, which would result in the players from that team being returned multiple times