I have 2 tables that I need to get information from, and would like to get the information in one single query.
The situation is this :
table "matches" :
id
team_A_id
team_B_id
table "teams" :
id
name
The objective is to retrieve information from table "matches" (football matches) and join the information with the table "teams". I need this because my webservice provider doesn't have the xml data in my language (portuguese), and so I need to offer my client the option to translate certain team names to portuguese, otherwise I'd add the team names directly on the "matches" table. The problem is that I need to JOIN the 2 tables with 2 id's. I know how to join tables with 1 id in common, but can't figure out how to do it with 2 id's, and mantaining the information from the 2 teams involved in each match intact.
Is this possible? Or do I have to create separate queries?
select match.*, teama.name, teamb.name
from matches as match
inner join teams as teama on teama.id = match.team_A_id
inner join teams as teamb on teamb.id = match.team_B_id
would work in SQL Server and presumably MySQL too.
Include the teams table a second time (with a different alias) and treat the query as being between three tables:
SELECT *
FROM matches m
JOIN teams t1 ON m.team_A_id = t1.id
JOIN teams t2 ON m.team_B_id = t2.id
SELECT *
FROM matches m, team t1, team t2
WHERE m.team_A_id = t1.id
AND m.team_B_id = t2.id
Related
i have a problem in MySQL where I use the COUNT function for conditions. However, when combining this with joins, although I use grouping, the COUNT values include ALL rows, even the ones filtered out.
I'm providing a minimal working example, which however maybe does not make a practical sense or is designed smartly.
So assume I have 3 tables:
products with fields: productId, name, active (boolean)
teams with fields: teamId, name
rel_production with fields: teamId, productId
So basically I have products and teams with ids and names. Products can be active (lets say that means that they are still in production or so).
And then I have a relation which team is working on which product.
To explain my problem, assume the following minimal amount of data to clarify the problem is contained inside the tables:
products
teams
rel_production
Now the query that I want to do is, in plain english: "I want all teams that are working on exactly 2 products while atleast one product must be active."
The query in general works and is the following in mysql:
SELECT
teams.*,
"r_count:",
r_count.*,
COUNT(r_count.productId),
"r_active:",
r_active.*,
"p_active:",
p_active.*
FROM teams
INNER JOIN rel_production r_active ON r_active.teamId = teams.teamId
INNER JOIN products p_active ON p_active.productId = r_active.productId AND p_active.active
INNER JOIN rel_production r_count ON r_count.teamId = teams.teamId
GROUP BY teams.teamId, r_active.teamId
HAVING COUNT(r_count.productId) = 2 #4 is the problem!!!!!!!!!!!!!
Now them problem is with team 1. Because it is working on 2 active products, COUNT(r_count.productId) will be 4 and not 2. So my query will filter it out.
Here is the screenshot with the result without the HAVING clause:
I see why this happens, because the two inner joins on rel_production will cause 4 rows to be generated. But then they are merged always together to one using the GROUP BY. So what I need is the COUNT after the GROUP and not before.
How can I fix this?
Perform the filtering on teams in a separate subquery, and then join to that:
SELECT
t1.teamId,
t1.name
FROM teams t1
INNER JOIN
(
SELECT t1.teamId
FROM rel_production t1
INNER JOIN products t2
ON t1.productId = t2.productId
GROUP BY t1.teamId
HAVING COUNT(DISTINCT t1.productId) = 2 AND SUM(t2.active) > 0
) t2
ON t1.teamId = t2.teamId;
SQLFiddle
i have a system that can get member information. i want my system to automatically get the name of the awardee. The conditions are if the member have recruited 6 people, he/she sold 15 soaps and his/her downlines sold 15 soaps each. Im using mysql and VB.NET so far i have this query.
SELECT *
FROM members m
LEFT JOIN
geneology g
ON SUM(m.status) >=90 AND
m.upline = g.parent_id;
but i get
1111 error - invalid use of group function
Table 1 has columns
id, name, status 'This is where the soap data are stored', downlines, upline
Table 2 has columns
id, parent_id, child_id
Please help im new to sql queries
First of all, the ON clause defines the criteria used to match the rows of the two tables, so that SUM() >= 90 is not supposed to stay there (in fact, that's why you're getting that error).
I will assume that for a person on table members, upline is the ID of the member that recruited him/her. If that's correct, you can build your query like this:
select t1.id, t1.name
from members t1
join geneology t2
on t1.id = t2.parent_id
join members t3
on t2.child_id = t3.upline
where t1.status = 15
group by t1.id, t1.name
having count(distinct t3.id) = 6 and
sum(t3.status) = 90
This will use the members table twice, once for the parent and once for the children, and the two tables are correlated by the geneology table.
The condition in the where clause is for the parent, then you group the child data for each parent, and only return the parents whose children satisfiy the conditions in the having clause.
Context
I have been fiddling with a small fooseball hobby database to keep track of matches, players and goals. And came across a problem i don't quite know how to fix.
The match table has two foreign keys both pointing to tID in the team table.
The thought was that i later would be able to do a SELECT to see what teams (by name) played against eachother in a given match.
select * from `Fooseball`.`match`
INNER JOIN team T1
ON Fooseball.`match`.mHome_Team = T1.tID
INNER JOIN team T2
ON Fooseball.`match`.mAway_Team = T2.tID
WHERE mID=1
Question
1 Is their a better way to archive this, than creating two primary keys. Like, an intermediate table?
2 How can i construct my select statement so i can name the tName columns as "home" and "away" or something else? When i try and say
INNER JOIN team AS T1
Nothing changes.
Unstated additional requirements notwithstanding, this is pretty much how I would do it.
To rename columns in the result, you would do something like
SELECT m.mDate AS match_date, T1.tName AS home_team, T2.tName AS away_team
FROM Fooseball.`match` m
INNER JOIN team T1
ON m.mHome_Team = T1.tID
INNER JOIN team T2
ON m.mAway_Team = T2.tID
WHERE mID=1
For reporting, you can alias your columns with mixed case and spaces (eg. "Home Team") by enclosing the alias in double quotes.
I have 2 tables:
table_name: user_tracking
With columns: id, bill_no, container_type, origin_id, destination_id
table_name: sea_ports
With columns: id, bill_no, port_name
I want to write a single query to get the origin port_name and the destination port_name.
my query is :
select a.container_type,
b.port_name as origin_port
from user_tracking a
left join sea_ports b
on a.bill_no = b.bill_no
where a.bill_number = '$bill_no'
How do I join the two columns origin_id and destination_id on the same field id from the table sea_ports to get two different outputs?
You need to join the table sea_ports twice so you can get the port_name for each origin and destination. And One more thing, I guess, you need need to use INNER JOIN rather than LEFT JOIN because there will always be destination and origin right? :D
SELECT a.ID,
a.bill_no,
a.container_type,
b.port_name AS Origin_name,
c.port_name AS Destination_name
FROM user_tracking a
INNER JOIN sea_ports b
ON a.origin_id = b.id
INNER JOIN sea_ports c
ON a.destination_id = c.id
WHERE a.bill_number = '$bill_no'
As a sidenote, the query is vulnerable with SQL Injection if the value(s) came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?
To filter a table output of selected entries from a single table i would need something like a multiple JOIN request through several tables.
I want to filter a table of people by a special column in the table. Lets say this column is "tasks." Now tasks is also another table with the column "people" and the values between those two tables are connected with an existant "join" table in the database, which is matching several IDs of one table to each ID of the other table.
Now if this would be simple as that i could just filter with an INNER JOIN and a special condition. The problem is, that the entries of the table "tasks" are connected to another table over a "join" table in the database. To simplify things lets say it is "settings". So each "task" consists of several "settings" which are connected via a join table in their IDs.
So what is the input?
I got an array of IDs, which are representing the settings-ids i do not want to be shown.
What should be the output?
As already said i want a filtered output of "people" while the filter is "settings."
I want the sql request to return each entry of the table "people" with only joined tasks that are not joining any of the "setting-ids" from the array.
I hope you can help me with that.
Thanks in advance!
Example
Settings-Table:
1. Is in progress
2. Is important
3. Has unsolved issues
Tasks-Table: (settings.tasks is the join table between many tasks to many settings)
1. Task from 01.01.2012 - JOINS Settings in 1 and 3 (In progress + unsolved issues)
2. Task from 02.01.2012 - JOINS Settings in 2 (Is important)
3. Task from 03.01.2012 - JOINS Settings in 1 and 2 (...)
People-Table: (people.tasks is the join table between many people to many tasks)
1. Guy - JOINS Tasks in 1, 2, 3 (Has been assigned to all 3 tasks)
2. Dude - JOINS Tasks in 1 (Has been assigned to the Task from 01.01.2012)
3. Girl - JOINS Tasks in 2, 3 (...)
Now there is an array passed to a sql query
[2,3] should return noone because every person is assigned in a task that was either important or had unsolved issues!
[3] would return me only the person "Girl" because it is the only one that is assigned to tasks (2 and 3) that had no unsolved issues.
I hope it is clear now. :)
SELECT DISTINCT PEOPLE.*
FROM PEOPLE INNER JOIN PEOPLE_TASKS ON PEOPLE.PERSON_ID = PEOPLE_TASKS.PERSON_ID
WHERE TASK_ID NOT IN (SELECT DISTINCT TASK_ID
FROM TASK_SETTINGS
WHERE SETTING_ID = <Id you don't want>)
EDIT (for supplying multiple setting ids you don't want)
SELECT DISTINCT PEOPLE.*
FROM PEOPLE INNER JOIN PEOPLE_TASKS ON PEOPLE.PERSON_ID = PEOPLE_TASKS.PERSON_ID
WHERE TASK_ID NOT IN (SELECT DISTINCT TASK_ID
FROM TASK_SETTINGS
WHERE SETTING_ID IN (<Id you don't want>))
First you have to join table people and table tasks with the join table, let's call it people_tasks.
select distinct p.* from people p
inner join people_tasks pt on p.people_id = pt.people_id
inner join tasks on t.tasks_id = pt.tasks_id
Then you have to join table tasks and table settings with the join table, let's call it tasks_settings. You have to join them in the current select.
select distinct p.* from people p
inner join people_tasks pt on p.people_id = pt.people_id
inner join tasks on t.tasks_id = pt.tasks_id
inner join tasks_settings ts on t.tasks_id = ts.tasks_id
inner join settings s on s.settings_id = ts.settings_id
and now you have all people connected with its tasks and its settings. Finally you need the restriction. With the people with the settings selected, you choose the others like this:
select distinct p.people_id from people p
inner join people_tasks pt on p.people_id = pt.people_id
where p.people_id not in (
select distinct p2.people_id from people p2
inner join people_tasks pt2 on p2.people_id = pt2.people_id
inner join tasks t2 on t2.tasks_id = pt2.tasks_id
inner join tasks_settings ts2 on t2.tasks_id = ts2.tasks_id
inner join settings s2 on s2.settings_id = ts2.settings_id
where s2.settings_id in (list of ids)
)