I have a database with 3 tables records, categories, relational.
records (id, lat, lng)
categories (c_id, c_value)
relational (r_id, c_id)
records
id | lat | lng
----------------------
1 23.57258 -35.28412
2 23.54855 -35.18881
3 23.74128 -35.17469
categories
c_id | c_value
---------------
100 groceries
101 bags
102 drinks
relational
id | c_id
------------
1 100
1 102
2 101
3 100
The relational.r_id = records.id and the relational.c_id = categories.c_id
I want to take pairs from records with different c_value, so I want to make a self join in records and inner join in categories and relational.
I've made this without the self join in records
SELECT id, lat, lng, c_value
FROM records
JOIN relational
ON records.id = relational.id
JOIN categories
ON relational.c_id = categories.c_id
WHERE c_value = "V1"
I tried something like this but it didn't work. I have problem with the R1.c_value.
SELECT R1._id, R1.lat, R1.lng, R1.c_value, R2._id, R2.lat, R2.lng,
R2.c_value
FROM records R1, records R2
JOIN relational
ON records.id = relational.id
JOIN categories
ON relational.c_id = categories.c_id
WHERE R1.c_value = "groceries" AND R2.c_value = "bags"
Do you know how can I combine those 3 joins in order to take 2 rows from records with the criteria of the other tables?
I want to have an output like this:
For "groceries" and "bags" as c.value
1 | 23.57258 | -35.28412 | groceries | 2 | 23.54855 | -35.18881 | bags
You can self join records table along with categories and relational like this:
SELECT r1.id, r1.lat, r1.lng, r2.id, r2.lat, r2.lng, c.c_value
FROM records r1 JOIN relational rl ON r1.id = rl.r_id
JOIN records r2 ON r2.id = rl.r_id
JOIN categories c ON rl.c_id = c.c_id
WHERE r1.id <> r2.id;
I finally found exactly what I wanted. My query should be like this. Thanks for the help and the idea anyway.
SELECT r1.id, r1.lat, r1.lng, c1.c_value, r2.id, r2.lat, r2.lng, c2.c_value
FROM records r1 JOIN relational rl1 ON rl1.id = r1.id
JOIN categories c1 ON rl1.c_id = c1.c_id
JOIN records r2 JOIN relational rl2 ON rl2.id = r2.id
JOIN categories c2 ON rl2.c_id = c2.c_id
WHERE c1.c_value = "groceries" AND c2.c_value = "bags"
Related
I tried all the similar questions but I can not get what I want.
Need help with Joining the table.
1. Table bookings:
id = 1 customer_id = 1 booking_details = 'venue etc'
2. Table customers:
id = 1 name = 'John Citizen'
3. Table: booking_objects:
id = 1 booking_id = 1 object_id = 1
id = 2 booking_id = 1 object_id = 2
4. Table objects:
id = 1 name = 'Object 1'
id = 2 name = 'Object 2'
I want to join tables to I get "Venue etc, Jhon Citizen, Oject 1, Object 2"
currently I am getting "Venue etc, Jhon Citizen" using below query
$this->db->select("bookings.bookig_details, customers.name as customer_name, objects.name as object_name")->join("customers", "customers.id = bookings.customer_id", "left outer")
In your requirement, Venue etc, Jhon Citizen, Object 1, Object 2 are mentioned. Object 1 and Object 2 comes under same column i.e, objects.name.
As per my understanding you need booking_details, customer_name, obj_name are your required columns.
select b.booking_details, c.name as customer_name, o.name as obj_name
bookings b
inner join
customers c
on b.customer_id = c.id
inner join
booking_objects bo
on b.id = bo.id
inner join
objects o
on bo.object_id = o.id
You can change the join types based on your requirement.
Instead of using values of the required output, it would have been better to use required columns in your question for clarity.
You need to use Self JOIN
like this.
select b.booking_details,c.name 'customer_name',o1.name 'o1Name',o2.name 'o2Name'
FROM objects o1
join objects o2 ON o1.id = 1 and o2.id = 2
join booking_objects bo on o1.id = bo.object_id
join bookings b on b.customer_id = bo.booking_id
join customers c on bo.booking_id = c.ID
sqlfiddle:http://sqlfiddle.com/#!9/594973/14
Table transport
Id | FirstLevSubcat | SecondLevSubcat | ThirdLevSubcat
--------------------------------------------------------
8 | 4 | 27 | 1418
Table categories
Id | CategoriesUrl
--------------------
4 | cars
27 | audi
1418 | audi-100
Query if not to use categories table (without inner join) would be like
SELECT count(*) FROM transport
WHERE FirstLevSubcat = 4 AND SecondLevSubcat = 27 AND ThirdLevSubcat = 1418
Trying to get the same result using INNER JOIN
SELECT count(*) FROM transport main_table
INNER JOIN categories cat_table_first ON cat_table_first.IdRows = main_table.FirstLevSubcat
INNER JOIN categories cat_table_second ON cat_table_second.IdRows = main_table.SecondLevSubcat
INNER JOIN categories cat_table_third ON cat_table_third.IdRows = main_table.ThirdLevSubcat
WHERE
cat_table_first.CategoriesUrl = 'cars'
AND cat_table_second.CategoriesUrl = 'audi'
AND cat_table_third.CategoriesUrl = 'audi-100'
At first sight all works
But is such query ok? May be can improve something?
Your query is correct. You can also do it in following way:
SELECT count(*) FROM transport main_table
INNER JOIN categories cat_table_first ON cat_table_first.IdRows = main_table.FirstLevSubcat and cat_table_first.CategoriesUrl = 'cars'
INNER JOIN categories cat_table_second ON cat_table_second.IdRows = main_table.SecondLevSubcat and cat_table_second.CategoriesUrl = 'audi'
INNER JOIN categories cat_table_third ON cat_table_third.IdRows = main_table.ThirdLevSubcat and cat_table_third.CategoriesUrl = 'audi-100'
You can also do it using 3 EXISTS block.
SELECT count(*) FROM transport main_table
WHERE
EXISTS (SELECT NULL FROM categories WHERE main_table.FirstLevSubcat=categories.IdRows AND categories.CategoriesUrl ='cars')
AND
EXISTS (SELECT NULL FROM categories WHERE main_table.SecondLevSubcat=categories.IdRows AND categories.CategoriesUrl ='audi')
AND
EXISTS (SELECT NULL FROM categories WHERE main_table.ThirdLevSubcat=categories.IdRows AND categories.CategoriesUrl ='audi-100')
I've got a SELECT with multiple JOINS for a paginated Tableview. In general this is working for unfiltered results.
The query looks like this:
SELECT seltable.*,
tbl2.name AS tbl2name,
tbl3.name AS tbl3name,
tbl4.name AS tbl4name
FROM
( SELECT * FROM selecttable
WHERE value = 99
ORDER BY datetime DESC
LIMIT 50 OFFSET 0 )
AS seltable
LEFT JOIN table1 AS tbl1 ON seltable.tbl1_uid = tbl1.uid
LEFT JOIN table2 AS tbl2 ON tbl1.tbl2_uid = tbl2.uid
LEFT JOIN table3 AS tbl3 ON tbl2.tbl3_uid = tbl3.uid
LEFT JOIN table4 AS tbl4 ON tbl3.tbl4_uid = tbl4.uid;
Now I've got no clue how to accomplish filtering the results with a condition related to one of the join tables.
When I just set a:
LEFT JOIN tablex AS table ON foreign_table.tblx_uid = table.uid AND {condition}
this condition regards only to the 50 results of the nested SELECT.
Is there any way to achieve using WHERE clauses on the JOIN tables in this scenario?
For sample data see http://sqlfiddle.com/#!2/fad4d/2
Expected results:
to get x team records limited to 5 team uids, where Tournament2 is one of the related tournaments for the team.
Best regards
w1ll1
Try not controlling the pagination in that subquery, instead just use a more conventional query with a composite where clause. HOWEVER, because you are using left joins take care adding filters through the where clause that would override the outer join to produce the effect of an inner join.
SELECT seltable.*,
tbl2.name AS tbl2name,
tbl3.name AS tbl3name,
tbl4.name AS tbl4name
FROM selecttable AS seltable
LEFT JOIN table1 AS tbl1 ON seltable.tbl1_uid = tbl1.uid
LEFT JOIN table2 AS tbl2 ON tbl1.tbl2_uid = tbl2.uid
LEFT JOIN table3 AS tbl3 ON tbl2.tbl3_uid = tbl3.uid
LEFT JOIN table4 AS tbl4 ON tbl3.tbl4_uid = tbl4.uid
WHERE seltable.value = 99
...
ORDER BY seltable.datetime DESC
LIMIT 50 OFFSET 0
Alternatively use more subqueries, like this:
SELECT seltable.*,
tbl2.name AS tbl2name,
tbl3.name AS tbl3name,
tbl4.name AS tbl4name
FROM
( SELECT * FROM selecttable
WHERE value = 99
ORDER BY datetime DESC
LIMIT 50 OFFSET 0 )
AS seltable
LEFT JOIN ( SELECT uid, name
FROM table1
WHERE 1=1 -- amend to suit
) AS tbl1 ON seltable.tbl1_uid = tbl1.uid
LEFT JOIN ( SELECT uid, name
FROM table2
WHERE 1=1 -- amend to suit
) AS tbl2 ON tbl1.tbl2_uid = tbl2.uid
LEFT JOIN ( SELECT uid, name
FROM table3
WHERE 1=1 -- amend to suit
) AS tbl3 ON tbl2.tbl3_uid = tbl3.uid
LEFT JOIN ( SELECT uid, name
FROM table4
WHERE 1=1 -- amend to suit
) AS tbl4 ON tbl3.tbl4_uid = tbl4.uid;
Here is another attempt, based on your sqlfiddle it appears that INNER JOINS may be used:
SELECT theteam.*,
trnmnt.name AS tournamentname,
cat.name AS categoryname,
sport.name AS sportname
FROM (
SELECT * FROM team
ORDER BY team.name ASC )
AS theteam
INNER JOIN tournament_team AS tntm ON tntm.team_uid = theteam.uid
INNER JOIN tournament AS trnmnt ON tntm.tournament_uid = trnmnt.uid AND trnmnt.name = 'Tournament2'
INNER JOIN category AS cat ON trnmnt.category_uid = cat.uid
INNER JOIN sport ON cat.sport_uid = sport.uid
LIMIT 5 OFFSET 0
;
The result of that query is:
| UID | NAME | TOURNAMENTNAME | CATEGORYNAME | SPORTNAME |
|-----|--------|----------------|--------------|-----------|
| 2 | Team02 | Tournament2 | Germany | Soccer |
| 3 | Team03 | Tournament2 | Germany | Soccer |
| 4 | Team04 | Tournament2 | Germany | Soccer |
| 5 | Team05 | Tournament2 | Germany | Soccer |
| 6 | Team06 | Tournament2 | Germany | Soccer |
i have two tables
IDartist name
----------- -----------
1 akon
2 50 cent
IDsong name IDartist IDauthor IDcomposer IDmusicProducer
------ ---- -------- -------- --------- ---------------
1 lonley 1 2 1 2
how i out the name of whice IDartist,IDauthor,IDcomposer,IDmusicProducer ?
i tried to do this and its not working:
SELECT
songs.`IDsong`,
songs.`IDartist`,
songs.`name`,
songs.`IDgenre`,
songs.`IDauthor`,
songs.`IDcomposer`,
songs.`IDmusicProducer`,
artists.`name` As artists_name,
songs_genres.`name` As genres_name
FROM `songs`
LEFT OUTER JOIN `artists` ON (songs.`IDartist` = artists.`IDartist` OR songs.`IDauthor` = artists.`IDartist` OR songs.`IDcomposer` = artists.`IDartist` OR songs.`IDmusicProducer` = artists.`IDartist`)
LEFT OUTER JOIN `songs_genres` ON (songs.`IDgenre` = songs_genres.`IDgenre`)
WHERE songs.`IDsong`=XXX
In order to get the names of the artist, author, composer, and producer, you will have to join the artists table to the songs table for separate times. The query should look something like the following:
SELECT
s.IDsong, s.name,
a1.name AS artists_name,
a2.name AS author_name,
a3.name AS composer_name,
a4.name AS producer_name,
sg.name AS genres_name
FROM songs AS s
JOIN artists AS a1 ON s.IDartist = a1.IDartist
JOIN artists AS a2 ON s.IDauthor = a2.IDartist
JOIN artists AS a3 ON s.IDcomposer = a3.IDartist
JOIN artists AS a4 ON s.IDmusicProducer = a4.IDartist
JOIN songs_genres AS sg ON s.IDgenre = sg.IDgenre
If there may not be an artist, author, composer, and producer for a record then you will have to use LEFT JOIN on the tables instead.
I'm rather new to normalizing tables and I'm having some troubles wrapping my head around getting the correct information out of 3 tables. I made an example involving reserving books out of different libraries. I have 3 tables. Books, locations, reservations (listed below):
//SQL query:
$sql =
"SELECT * FROM books
JOIN (location LEFT JOIN reservations ON location.locID = reservations.locID)
ON books.bookID = location.bookID
WHERE location.locID=2
";
and the output I was hoping to achieve if I were to list the books in Campus B:
title |locName |status
Book 1|Campus B|1
Book 2|Campus B|0
Book 3|Campus B|0
Book 4|Campus B|0
Book 5|Campus B|1
For some reason I'm definitely not getting the output I think I should, and I was curious if anyone has some suggestions. I'm sure once I see whats going on I'll understand what I did incorrectly.
table: books
bookID|title
1 | Book 1
2 | Book 2
3 | Book 3
4 | Book 4
5 | Book 5
table: location
locID|locName
1 | campus A
2 | campus B
3 | campus C
table: reservations
bookID|locID|status
1 | 1 | 1
3 | 1 | 1
4 | 1 | 1
1 | 2 | 1
5 | 2 | 1
4 | 3 | 1
5 | 3 | 1
I think this is more in line with what you're looking for:
SELECT *
FROM books b
LEFT JOIN reservations r ON b.bookID = r.bookID
JOIN location l on r.locID = l.locID
WHERE l.locID = 2
This will return a list of the books reserved at the location with locID=2.
In this case I have a LEFT JOIN to preserve your original query, however given your WHERE clause any records with NULL in the location.locID field will not be selected.
Therefore, I could re-write your query with all INNER joins, like so:
SELECT *
FROM books b
JOIN reservations r ON b.bookID = r.bookID
JOIN location l on r.locID = l.locID
WHERE l.locID = 2
Other queries that you might find interesting:
Get ALL books, regardless of whether or not they are reserved anywhere:
SELECT *
FROM books b
LEFT JOIN reservations r ON b.bookID = r.bookID
JOIN location l on r.locID = l.locID
Get ALL locations, regardless of whether or not there are books reserved there:
SELECT *
FROM books b
JOIN reservations r ON b.bookID = r.bookID
RIGHT JOIN location l on r.locID = l.locID
Get ALL books and ALL locations:
SELECT *
FROM books b
LEFT JOIN reservations r ON b.bookID = r.bookID
RIGHT JOIN location l on r.locID = l.locID
SELECT
books.title
, location.locName
, IFNULL(reservations.status, 0) status
FROM
books
JOIN location
LEFT JOIN reservations ON (
location.locID = reservations.locID
AND books.bookID = location.bookID
)
WHERE location.locID = 2