-1

I have this schema:

CLUB(Name, Address, City)
TEAM(TeamName, club)
PLAYER(Badge, teamName)
MATCH(matchNumber, player1, player2, club, winner)
  • Club in TEAM references Name in CLUB;
  • teamName in PLAYER references TeamName in TEAM;
  • Player 1, player 2, winner in MATCH reference Badge in PLAYER;
  • Club in MATCH references Name in CLUB;

A player can be part of only one team. Matches can be played between teammates. A team can have only one club.

And I need to do this algebra relation:

Extract the players who have always won and the related team.

I know that this can be done by using the division operation structured as well:

r(A, B) / s(B)

The fact is that I don't know how to set up it. In the first relation I have an attribute A which is the one that I wanna extract (I guess), so it should be "TeamName". The secondo one (B) should be one attribute which is common with s(B) (where s(B) is a subset of r(A, B)). In this case can it be the attribute "Winner"?

JimBelushi2
  • 285
  • 1
  • 3
  • 18
  • [Relational Division and SQL - Robert Soulé](http://www.inf.usi.ch/faculty/soule/teaching/2016-fall/db/division.pdf) – Lukasz Szozda Jun 06 '18 at 07:37
  • Thanks, but this explains it in terms of SQL. I'm looking for a solution in relational algebra – JimBelushi2 Jun 06 '18 at 07:40
  • Please use correct tags. – Lukasz Szozda Jun 06 '18 at 07:40
  • This is a puzzling schema. What are the keys for the relations? What are the Foreign Key constraints? Does each `PLAYER` always play for the same `TeamName`? Are there many Teams within each `club`? In the `MATCH` relation, is `winner` a `player` or a `TeamName` or a `club`? In `MATCH` what is the `club` attribute showing? Why do you say this can be done using the division operation? Hint: the players who have always won are the players who have never lost. You don't need division to find them. Gotcha: what about players who've never played -- then they've never lost, have they "always won"? – AntC Jun 06 '18 at 11:00
  • I would like to use the Division to understand how it works. – JimBelushi2 Jun 06 '18 at 12:22
  • Hi. Please edit clarifications into your post, not comments. Please read & act on hits googling 'stackexchange homework'. Show all the parts you can do. Tell us your textbook including edition & quote a definition of division & an example of how it was applied to a problem. Here your wording is so vague that it is no wonder you can't apply what you have been told, and it means that you are asking us to do all the work. Also division isn't needed here, why do you think it is? – philipxy Jun 06 '18 at 14:35
  • @AntC & JimBelushi2 Constraints (including CKs & FKs) are not needed to query. What is necessary & sufficient are the table meanings (what a row in a table says about the situation) and any business rules that the query specification relies on. (Constraints follow from the meanings & rules.) Eg "and the related team" only makes sense when a player has exactly one related team (whatever "related" means), but the RA query for it is the same as the query for "and the related teams". [Re querying.](https://stackoverflow.com/a/24425914/3404097) PS I agree re clarifying "always won". – philipxy Jun 06 '18 at 15:49
  • @Philipxy you know that I know that CKs & FKs are not needed to query. Joins (Natural & equi-) are needed. The easiest way to ask what joins to what is via FKs. Giving CKs and FKs for a schema is a good habit to encourage. Jim as suggested please edit the q to show what joins to what. And use consistent case for your naming. I also personally prefer same attribute name across different relations if they denote 'same thing'. – AntC Jun 07 '18 at 07:56
  • @AntC & JimBelushi2 Asking for constraints when they are not needed & without asking for what is actually needed (meanings) & without explaining why things that are not needed are asked for misdirects, promotes misconceptions & does not address how to solve/approach the problem. Having FKs does give some info about what should have been requested & given so it eases & promotes guessing--for better & worse. [Re composing queries.](https://stackoverflow.com/a/24425914/3404097) – philipxy Jun 07 '18 at 13:11
  • Thanks for adding the cross-refs. Yes a query asking for "always" something or "X that have all Y" might indicate using relational division. I'm struggling to see how I could bend this query to use division. Have you been given this schema and question? Or are you trying to concoct an example? Does "Matches can be played between teammates." mean _only_ between teammates? How about instead a query: "players who have played everybody in team Y and always beaten them"? (That is, even though they might have played people from other teams and lost, or not played everybody in team Z.) – AntC Jun 08 '18 at 05:24
  • Why does the query ask for "... players who have ... and the related team."? Relation `PLAYER` gives you the related team for each player. Adding that on to the result is not exercising much, compared to the complexity of writing a divide. – AntC Jun 08 '18 at 05:29
  • I found the schema and the question in an exam of my course of the last year. A. player can have a match with a teammates or a player of another team, this is not important. I think that in an hypothetic tournament, the winner is who have beaten everyone, included his teammates. – JimBelushi2 Jun 08 '18 at 08:10

1 Answers1

2

OK let's assemble some building blocks.

Note on notation: I'm using the greek letters for relational operators; angle brackets around attribute names for them (usually shown suffixed); round brackets for the relation parameter.

  • Players that have played & won at least one match:

    PlayednWon := ρ⟨Badge := winner⟩(π⟨winner⟩(MATCH))
    
  • Players that have played & lost at least one match:

    PlayednLost := ρ⟨Badge := player1⟩(π⟨player1⟩(σ⟨winner ≠ player1⟩(MATCH)))
                   ∪
                   ρ⟨Badge := player2⟩(π⟨player2⟩(σ⟨winner ≠ player2⟩(MATCH)))
    
  • Players that have played & won every match they played. (i.e. have never played & lost)

    PlayednWonAll := PlayednWon - PlayednLost
    
  • Players that have never lost (possibly because they've never played at all)

    NeverLost := π⟨Badge⟩(PLAYER) - PlayednLost
    

Didn't need no relational division so far. Neither can I see it would make any of these more succinct. I'll add some more code later.

Are you reproducing the exam question faithfully? For example, are you told that MATCH includes at least one match between each possible pairing of players across the whole league? What has the course told you about the purposes for using division?

Does the exam question give extra marks for creative thinking around plausible scenarios? Is the lecturer some sort of sadist? Does the lecturer understand RA, or is this some sort of token coverage of the topic before getting on to the meat of SQL?

I could make a wild guess at why you're told "matches can be played between teammates."

  • Suppose the query were looking for players that have "always won" against everybody from a team. That's a good use for division.
  • Then there would be a point in reporting "related team": a given player might have "always won" against several different teams; and we'd want to report each such team -- not necessarily the player's 'home' team.
  • But it might include 'home' team (because "matches can be played between teammates"). Then there's a gotcha: no player can play themselves (presumably); then they need to have played and "always one" against everybody in their 'home' team except themselves.

Would marks be given in the exam for exploring all those possibilities?

Addit: Let's use division to find a subtle variant.

  • Another building block: pair up the winner and loser from each match (this is a variation on PlayednLost):

    WinnernLoser := ρ⟨Badge := player1⟩(π⟨winner, player1⟩(σ⟨winner ≠ player1⟩(MATCH)))
                    ∪
                    ρ⟨Badge := player2⟩(π⟨winner, player2⟩(σ⟨winner ≠ player2⟩(MATCH)))
    
  • Now those who've been on the winning side against everyone that's ever lost:

    PlayednBeatAll := WinnernLoser ÷ PlaydnLost
    // equivalently:  WinnernLoser ÷ π⟨Badge⟩(WinnernLoser)
    
    • Quick: what attribute(s) are in the result? Why?
    • Then how do we get the "related team" per the original question?
    • This is a subset (not nec. proper) of PlayednWonAll. Why?

Notice that with relation PlayednWonAll or PlayednBeatAll, there might be many players in the result: Anna has won every match she played; so has Barbara. How come? Because Anna has never played Barbara; there's no overall champion. In the case of PlayednBeatAll, it means Anna and Barbara have played everybody except each other.

What's the difference between PlayednWonAll as compared with PlayednBeatAll? Carla has played only one match, against Donna, which Carla won. Anna and Barabara played and won against not only Donna but also Emilia (neither played Carla). So Anna & Barbara appear in both results, Carla only in PlayednWonAll.

  • Here's a useless divide:

    ThinkAboutIt := WinnernLoser ÷ π⟨Badge⟩(PLAYER)
    
    • PLAYER possibly includes players who've never played. Then nobody can have beaten them. Even if every PLAYER has played:
    • PLAYER includes everybody who's "always won"; they can't have lost to themselves.
    • IOW ThinkAboutIt is always empty.

Gotcha's like this are why I think teaching relational divide is pointless. There's actually several variants of divide, each trying to cope differently with corner cases like empty relations or divisors with attributes not a subset of the dividend. (Or semantics like "always won" vs "never lost".) And lecturers/textbooks rarely get into the subtleties.

Furthermore divide is not available in SQL, so learning about it is of marginal benefit. Division can always be obtained by other operators, and usually those give a just as succinct expression, and an expression that's easier to understand. (I mean other RA operators: in SQL simulating divide needs ghastly code, as usual.) QED.

AntC
  • 2,623
  • 1
  • 13
  • 20