MySQL data fetching - mysql

I have trouble to understand how to fetch data from MySQL. Answer might by simple, but i'm stuck, and can't find any help over internet...
I have three tables, let's say first table is named series, second is teams and third id games.
Table structure is something like this:
series:
id
name
teams:
id
name
games:
series_id (relates to series.id)
hometeam_id (relates to teams.id)
visitorteam_id (relates to teams.id)
So my problem is fetching rows from games, where those id's need to be there names, not id's...
Result should be something like this:
"championship
wolverines
marines"
not like
"1
45
142"
Currently i'm fetching those series and teams tables to hashref (in perl) and taking id's from there. But there must be more efficient way to do that in one sql query instead of three.

You need to join the teams table twice (once for home team, second time for visitors)
SELECT g.*,h.name as hometeam_name,v.name as visitorteam_name FROM games g
INNER JOIN series s ON g.series_id=s.id
INNER JOIN teams h ON g.hometeam_id=h.id
INNER JOIN teams v ON g.visitorteam_id=v.id

Related

SQL giving me lines that doesn't exist?

While using this:
SELECT borrowbook.studentusername, borrowbook.schoolbookid,borrowbook.date,borrowbook.deadline, book.title, student.email, student.fname, student.lname
FROM borrowbook, book, student
I get many lines, but in my database I just have four lines in the borrowbook table, and while using this, I get some "lines" that doesn't exist. (Note: this works through php on a website, I cannot seem to make this work in mysql so I think I have done something)
Like that a person that had borrowed one book (line 1 in my list of borrowed books) suddenly has borrowed ten different books that I have not registered anyone to borrow. With date as to when it was loaned, and deadline just taken from one of the four lines I have registered.
Even the same person that is registered to borrow one book, suddenly shows up as if they borrowed it four times with different dates. Dates and deadline are taken from "borrowbook" while different names of students are taken from another table, since they have never been used in the "borrowbook" line.
I have tried this now in different ways and with different content and different tables, but still get many "made up" lines of loans that is not registered.
I know very little, but I am grateful for all help I can get. Articles help as well.
Without joins, you duplicate records. For a better practice, you should use explicit joins instead of implicit ones. If you have student.username and book.id fields, you can do something like this:
SELECT borrowbook.studentusername, borrowbook.schoolbookid,borrowbook.date,borrowbook.deadline,
book.title,
student.email, student.fname, student.lname
FROM borrowbook
INNER JOIN student ON borrowbook.studentusername=student.username
INNER JOIN schoolbook ON borrowbook.schoolbookid=schoolbook.id
INNER JOIN book ON schoolbook.isbn=book.isbn
;
You haven't specified any JOIN conditions in your query, and because of that tables will be CROSS JOIN-ed, i.e., every record from the borrowbook table is paired with every record from the book table which is then paired with every record from the student table. So if you have X, Y and Z number of records in each table respectively, you will get X * Y * Z records as a result.
You probably want to add join conditions such as (I'm just guessing column names):
SELECT borrowbook.studentusername, borrowbook.schoolbookid,borrowbook.date,borrowbook.deadline, book.title, student.email, student.fname, student.lname
FROM borrowbook, book, student
WHERE borrowbook.book_id = book.id and borrowbook.student_id = student.id

Averaging a one-to-one field will summing a one to many in MySQL

I put together this example to help
http://sqlfiddle.com/#!9/51db24
The idea is I have 3 tables. One is the "root" table, in this case person which has a score attached to it. They then have some category I need to group by person_cat.cat and a one to many field called CS.
I would like to query for the average of the score, the sum of the one to many field person_co.co and group by the category.
SELECT
person_cat.cat,
person.id,
SUM(person_co.co),
AVG(person.cs)
FROM
person
LEFT JOIN person_co USING (id)
LEFT JOIN person_cat USING (id)
GROUP BY cat;
The issue I'm currently having is the average gets thrown off due to the join for the one to many. I can accomplish this with multiple queries, which is ok if that is the answer. However it would be nice to get this as one query.

SQL Inner Join With Multiple Columns

I've got 2 tables - dishes and ingredients:
in Dishes, I've got a list of pizza dishes, ordered as such:
In Ingredients, I've got a list of all the different ingredients for all the dishes, ordered as such:
I want to be able to list all the names of all the ingredients of each dish alongside each dish's name.
I've written this query that does not replace the ingredient ids with names as it should, instead opting to return an empty set - please explain what it that I'm doing wrong:
SELECT dishes.name, ingredients.name, ingredients.id
FROM dishes
INNER JOIN ingredients
ON dishes.ingredient_1=ingredients.id,dishes.ingredient_2=ingredients.id,dishes.ingredient_3=ingredients.id,dishes.ingredient_4=ingredients.id,dishes.ingredient_5=ingredients.id,dishes.ingredient_6=ingredients.id, dishes.ingredient_7=ingredients.id,dishes.ingredient_8=ingredients.id;
It would be great if you could refer to:
The logic of the DB structuring - am I doing it correctly?
The logic behind the SQL query - if the DB is built in the right fashion, then why upon executing the query I get the empty set?
If you've encountered such a problem before - one that requires a single-to-many relationship - how did you solved it in a way different than this, using PHP & MySQL?
Disregard The Text In Hebrew - Treat It As Your Own Language.
It seems to me that a better Database Structure would have a Dishes_Ingredients_Rel table, rather than having a bunch of columns for Ingredients.
DISHES_INGREDIENTS_REL
DishesID
IngredientID
Then, you could just do a much simpler JOIN.
SELECT Ingredients.Name
FROM Dishes_Ingredients_Rel
INNER JOIN Ingredients
ON Dishes_Ingredients.IngredientID = Ingredients.IngredientID
WHERE Dishes_Ingredients_Rel.DishesID = #DishesID
1. The logic of the DB structuring - am I doing it correctly?
This is denormalized data. To normalize it, you would restructure your database into three tables:
Pizza
PizzaIngredients
Ingredients
Pizza would have ID, name, and type where ID is the primary key.
PizzaIngredients would have PizzaId and IngredientId (this is a many-many table where the primary key is a composite key of PizzaId and IngredientID)
Ingredients has ID and name where ID is the primary key.
2. List all the names of all the ingredients of each dish alongside each dish's name. Something like this in MySQL (untested):
SELECT p.ID, p.name, GROUP_CONCAT(i.name) AS ingredients
FROM pizza p
INNER JOIN pizzaingredients pi ON p.ID = pi.PizzaID
INNER JOIN ingredients i ON pi.IngredientID = i.ID
GROUP BY p.id
3. If you've encountered such a problem before - one that requires a single-to-many relationship - how did you solved it in a way different than this, using PHP & MySQL?
Using a many-many relationship, since that what your example truly is. You have many pizzas which can have many ingredients. And many ingredients belong to many different pizzas.
The reason you are getting an empty result is because you are setting a join condition that never gets satisfied. During the INNER join execution the database engine compares each record of the first table with each record of the second one trying to find a match where the id of the ingredient table record being evaluated is equal to ingredient1 AND ingredient2 AND so on. It would return some result if you create a record in the first table with the same ingredient in all 8 columns (testing purposes only).
Regarding the database structure, you choose a denormalized one creating 8 columns for each ingredient. There are a lot of considerations possible on this data structure (performance, maintainability, or just think if you are asked to insert a dish with 9 ingredients for example) and I would personally go for a normalized data structure instead.
But if you want to keep this, you should write something like:
SELECT dishes.name, ingredients1.name, ingredients1.id, ingredients2.name, ingredients2.id, ...
FROM dishes
LEFT JOIN ingredients AS ingredients1 ON dishes.ingredient_1=ingredients1.id
LEFT JOIN ingredients AS ingredients2 ON dishes.ingredient_2=ingredients2.id
LEFT JOIN ingredients AS ingredients3 ON dishes.ingredient_3=ingredients3.id
...
The LEFT join is required to get a result for unmatched ingredients (0 value when no ingredient is set reading your example)

Fetch data from table in mysql that must have corresponding records in another table

I want to show records from table name station where station have at least one song in song table.
Table structure
station
station_id
stration_name
station_description
song
song_id
station_id
song_location
Please suggest me the way to form query that shows me station data which have songs in song table.please specify a way that do not returns record with corresponding songs zero count.
What you're looking for is a INNER JOIN. You could join your stations table with your songs table by stations.station_id and songs.station_id. This will work because INNER JOIN only return rows for which the join-predicate is satisfied.
I've made an example available at SQL Fiddle, but I do recommend spending a few minutes understanding mechanics of JOIN.
SELECT DISTINCT something
FROM somewhere
JOIN somewhere_else
ON somewhere_else.other_thing = somewhere.thing;
You could join the tables together at station_id.
It looks like each song is linked to a spesific station. Meaning where these ID (station_id) is equal, the station has this song...

What's the best way to combine 2 tables in MYSQL and remove duplicates?

I have 2 tables:
matches TABLE
FIELDS: record, date, competition
outrights TABLE
FIELDS: record, competition
What I would like, is to select rows grouped by the different types of competition. Below are the statements that work fine when I treat each table seperately.
Firstly, from 'matches' and only if the date hasn't already past:
SELECT competition, date FROM matches WHERE date >= '$currentTime' GROUP BY competition
Followed by rows from 'outrights':
SELECT competition FROM outrights GROUP BY competition
This is all pretty straight forward, except the same competition values will often (but not always) appear in both tables. I have looked at many different methods (including LEFT and RIGHT JOINS), but haven't found a simple solution. Basically I want the different competition types that appear in both tables, without duplication. Is this possible?
Is this what you are looking for. A little confused by the question but it appears that you want a DISTINCT listing of the competition column from both tables
SELECT DISTINCT competition
FROM
(
SELECT competition FROM matches
UNION
SELECT competition from outrights
) AS t
If you need the distinct competitions that appear only in both tables and not just one or both you could use
SELECT DISTINCT competition
FROM
(
SELECT competition FROM matches INNER JOIN
outrights ON matches.competition = outrights.competition
) AS t