Joining the same table twice with different values - php

I'm trying to replace the value of "transfers.pickup_areas_group_id" and "transfers.drop_areas_group_id" with the values from the table "areas_group", using IDs
I'm using this query:
SELECT
transfers.id AS transfer_id,
transfers.name AS transfer_name,
transfers.pickup_areas_group_id AS transfer_pickup_areas_group_id,
transfers.drop_areas_group_id AS transfer_drop_areas_group_id,
transfers_pricing.vehicle_id AS vehicle_id,
transfers_pricing.date_start AS date_start,
transfers_pricing.date_end AS date_end,
transfers_pricing.price AS price
FROM transfers
INNER JOIN transfers_pricing ON transfers_pricing.transfer_id = transfers.id
I tried an extra INNER JOIN to replace the first value "transfers.pickup_areas_group_id", but I couldn't find a way to replace the second one "transfers.drop_areas_group_id"
I tried this query:
SELECT
transfers.id AS transfer_id,
transfers.name AS transfer_name,
transfers.pickup_areas_group_id AS transfer_pickup_areas_group_id,
areas_group.area_id AS pickup_area_ids,
transfers.drop_areas_group_id AS transfer_drop_areas_group_id,
transfers_pricing.vehicle_id AS vehicle_id,
transfers_pricing.date_start AS date_start,
transfers_pricing.date_end AS date_end,
transfers_pricing.price AS price
FROM transfers
INNER JOIN transfers_pricing ON transfers_pricing.transfer_id = transfers.id
INNER JOIN areas_group ON areas_group.id = transfers.pickup_areas_group_id
Thank you,

Basically, you need another join on areas_group; to disambiguate the two references to the same table, you need to use a table alias.
Actually, it is a good practice to use table aliases for all tables that come into play in the query: this makes the query shorter to read and write.
SELECT
t.id AS transfer_id,
t.name AS transfer_name,
t.pickup_areas_group_id AS transfer_pickup_areas_group_id,
ag1.area_id AS pickup_area_ids,
t.drop_areas_group_id AS transfer_drop_areas_group_id,
ag2.area_id AS drop_area_ids
tp.vehicle_id AS vehicle_id,
tp.date_start AS date_start,
tp.date_end AS date_end,
tp.price AS price
FROM transfers t
INNER JOIN transfers_pricing tp ON tp.transfer_id = t.id
INNER JOIN areas_group ag1 ON ag1.id = t.pickup_areas_group_id
INNER JOIN areas_group ag2 ON ag2.id = t.drop_areas_group_id

Related

MYSQL/PHP: Concat returning to many fields on LEFT JOIN

I had a SELECT query with a LEFT JOIN working as desired. I then added one more table via a smilar LEFT JOIN and now I am getting a wierd result. Basically, for a group_concat where I was getting one item for every record, I am getting eight records. I don't see why this is happening because the join to the new table is analagous to several other joins that do not have this problem (that I have omitted from the example for clarity).
Here is the query that is fine:
$sql = "SELECT t.*,
group_concat(tf.todoid) as `tftodoid`,
group_concat(tf.id) as `tfid`,
group_concat(tf.filedescript) as `tffiledescript`,
group_concat(tf.filename) as `tffilename`,
group_concat(tf.founderid) as `tffounderid`,
group_concat(tf.ext) as `tfext`,
group_concat(tf.lasttouched) as `tilt`
FROM titles `t`
LEFT JOIN titlefiles `tf`
ON (tf.todoid = t.id AND tf.founderid = '$userid')
WHERE t.userid='$userid'
GROUP BY t.id";
And here is the query with the extra join that is now spilling out the multiple copies of the items:
$sql = "SELECT t.*,
group_concat(tf.todoid) as `tftodoid`,
group_concat(tf.id) as `tfid`,
group_concat(tf.filedescript) as `tffiledescript`,
group_concat(tf.filename) as `tffilename`,
group_concat(tf.founderid) as `tffounderid`,
group_concat(tf.ext) as `tfext`,
group_concat(tf.lasttouched) as `tilt`,
group_concat(s.id) as `stepid`,
group_concat(s.step) as `steps`
FROM titles `t`
LEFT JOIN titlefiles `tf`
ON (tf.titleid = t.id AND tf.founderid = '$userid')
LEFT JOIN steps `s`
ON s.titleid = t.id
WHERE t.userid='$userid'
GROUP BY t.id";
Here is an example of output in JSON showing the difference:
First query:
"tfid":"56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81"
Second query:
"tfid":"56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81,56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81,56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81,56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81,56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81,56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81,56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81,56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81,56,57,58,59,60,61,62,63,64,65,66,67,68,75,76,81",
I suspect the problem has something to do with the JOIN or with the Group By statements but I can't see how to fix.
How can I ensure that I get only one fileid per file as opposed to eight?
Alter the line as follows:
group_concat(DISTINCT tf.id) as `tfid`,
This then only gets you the unique ids.
If you want them ordered add:
group_concat(DISTINCT tf.id ORDER BY tf.id ASC) as `tfid`,

Writing complex SQL query with 4 tables

I have 4 tables from which i want to output information with a single query and i'm not sure how to do that.
• From table1 i want to get all the records
• For each record from table1 i want to take out the SUM from field1 from all records in table2 on a matching id taken from table1
• For each record from table1 i want to take out the SUM from field1 from all records in table3 on a matching id taken from table1
• For each record from table1 i want to take out the value of a single record from table4 on a matching id taken from table1
EDIT:
Here is how i think the graphic for my request should look:
Here's my working code:
SELECT DISTINCT
i.id,
i.dateCreated,
i.dateBilled,
i.dateCompleted,
i.userId,
i.type,
i.status,
i.truck,
i.poNumber,
i.total,
i.billtoId,
i.shiptoId,
i.invoiceNumber,
i.loadNumber,
SUM(p.amount) as amountpaid,
c.name as billtoName
FROM `invoices` as i
LEFT JOIN `invoice_payments` as p ON i.id = p.invoice
RIGHT JOIN `companies` as c ON c.id = i.billtoId
GROUP BY i.id, i.invoiceNumber
You can see how i managed to get the SUM from all payments on my invoices with a left join. I'm trying to do the same for i.total, but as soon as i add another LEFT JOIN my calculations come up wrong and the result in amountpaid doubles
You can write this query with subqueries in the SELECT statement:
SELECT id,
(SELECT sum(field1) FROM t2 WHERE t2.idfrom1=t1.id) AS firstSum,
(SELECT sum(field1) FROM t3 WHERE t3.idfrom1=t1.id) AS secondSum,
(SELECT min(field1) FROM t4 WHERE t4.id=t1.f2 LIMIT 1) AS singleRecord
FROM t1
This is the idea, you just have to adapt it to your schema.
edit: updated from the drawing

UNION SELECT tables with inner join and GET values with "ALIAS"

So I have 2 tables, Matches and Teams, what I want to do is get some values from the match and Inner join "Teams" to get the names of both teams and add them to a php array later on (getting it all in one sql)
Matches
- IDMatch
- IDLocalTeam
- IDVisitorTeam
- Time
- Half
- Stopped
Teams
- IDTeam
- name
What I have by now is
$query = "SELECT * FROM `Matches`
INNER JOIN `Teams` ON `Matches`.IDLocalTeam = `Teams`.IDTeam
UNION SELECT * FROM `Matches` INNER JOIN `Teams`
ON `Matches`.IDVisitorTeam = `Teams`.IDTeam
ORDER BY IDMatch DESC;";
If someone could help me it would be great! Thanks alot
Wouldn't it be easier to use INNER JOIN twice? It's definitely quicker way of doing joins anyway.
SELECT
*
FROM
`Matches` m
INNER JOIN `Teams` t1
ON m.IDLocalTeam = t1.IDTeam
INNER JOIN `Teams` t2
ON m.IDVisitorTeam = t2.IDTeam
ORDER BY
m.IDMatch DESC;
Also start using aliases instead of table names to identify fields in query, it will SQL much smaller.

combine two different queries into one

I have the following query:
SELECT DISTINCT id, title
FROM
((SELECT
DISTINCT offers.id AS id, offers.title AS title
FROM offers
INNER JOIN categories
ON offers.category=categories.title
WHERE categories.title="Fashion clothes"
GROUP BY offers.id
ORDER BY offers.id)
UNION ALL
(SELECT
DISTINCT offers.id AS id, offers.title AS title
FROM offers
INNER JOIN cities
ON offers.city=cities.title
WHERE cities.title="Australia"
GROUP BY offers.id
ORDER BY offers.id)) as subquery
I would like to fetch from the table offers the rows that have category=Fashion clothes and city=Australia but when I use Union it returns all the rows .
I don't know how to make it work. If anyone can help i would appreciate it.
You don't need a union for this. Just join all the tables and have both conditions in you where clause:
SELECT
DISTINCT offers.id AS id, offers.title AS title
FROM offers
INNER JOIN categories
ON offers.category=categories.title
INNER JOIN cities
ON offers.city=cities.title
WHERE categories.title="Fashion clothes" AND cities.title="Australia"
ORDER BY offers.id
As noted by RubahMalam you don't even need the joins as you are joining the tables by title, so the query can be simplified to:
SELECT
DISTINCT offers.id AS id, offers.title AS title
FROM offers
WHERE offers.category="Fashion clothes" AND offers.city="Australia"
ORDER BY offers.id
However, it would probably be best to have separate unique id's in all your tables and use those to join them in your queries, but that's another story.
You just need :
SELECT id,title
FROM offers
WHERE category = "Fashion clothes" OR city = "Australia"
GROUP BY id,title
ORDER BY offers.id
You don't even need INNER JOIN for this. And as patrickh003 said, you don't even need GROUP BY if id is unique column.
If you want both, then you can use aggregation and a having clause:
SELECT o.id, o.title
FROM offers o
WHERE o.category = 'Fashion clothes' AND o.city = 'Australia'
GROUP BY o.id, o.title
HAVING COUNT(*) = 2
ORDER BY o.id;
If you can have duplicates in the offers table, then you need COUNT(DISTINCT o.category) in the HAVING clause instead of COUNT(*).

MySQL Using SUM with multiple joins

I have a projects table and a tasks table I want to do a query that gets all projects and the sum of the time_spent columns grouped by project id. So essentially list all projects and get the total of all the time_spent columns in the tasks table belonging to that project.
With the query posted below I get the latest added time_spent column and not the sum of all the columns.. :S
Below is the query I have at the moment:
SELECT `projects`.`id`, `projects`.`description`, `projects`.`created`,
`users`.`title`, `users`.`firstname`, `users`.`lastname`, `users2`.`title`
as assignee_title, `users2`.`firstname` as assignee_firstname,
`users2`.`lastname` as assignee_lastname,
(select sum(tasks2.time_spent)
from tasks tasks2
where tasks2.id = tasks.id)
as project_duration
FROM (`projects`)
LEFT JOIN `users`
ON `users`.`id` = `projects`.`user_id`
LEFT JOIN `users` as users2
ON `users2`.`id` = `projects`.`assignee_id`
LEFT JOIN `tasks` ON `tasks`.`project_id` = `projects`.`id`
GROUP BY `projects`.`id`
ORDER BY `projects`.`created` DESC
Below is my projects table:
Below is my tasks table:
Thanks in advance!
Usually this query will help you.
SELECT p.*, (SELECT SUM(t.time_spent) FROM tasks as t WHERE t.project_id = p.id) as project_fulltime FROM projects as p
In your question, you don't say about users. Do you need users?
You are on right way, maybe your JOINs can't fetch all data.
This query should do it for you.
Note, whenever you do a group by you must include every column that you select from or order by. Some MySql installations don't prevent you from doing this, but in the end it results in an incorrect result set.
As well you should never do a query as part of your SELECT statement, known as a sub-query, as it will result in an equal amount of additional queries in relation to the number of rows returned. So if you got 1,000 rows back, it would result in 1,001 queries instead of 1 query.
SELECT
p.id,
p.description,
p.created,
u.title,
u.firstname,
u.lastname,
a.title assignee_title,
a.firstname assignee_firstname,
a.lastname assignee_lastname,
SUM(t.time_spent) project_duration
FROM
projects p
LEFT JOIN
users u ON
u.id = p.user_id
LEFT JOIN
users a ON
a.id = u.assignee_id
LEFT JOIN
tasks t ON
t.project_id = p.id
GROUP BY
p.id,
p.description,
p.created,
u.title,
u.firstname,
u.lastname,
a.title,
a.firstname,
a.lastname
ORDER BY
p.created DESC

Categories