SQL query for multiple (one-to-many) tables in mysql database - mysql

I have a database with tours (group city tours with guide). What I need is a SQL query (for a mysql 5.1.54 database) that will eventually give me a PHP array with the information out of multiple tables combined. I'm able to accomplish this by doing a query just for the first 3 tables and then adding the information in table 4 and 5 within a foreach loop.
But, I need to use the query for searching/filtering (like: show all reservations where partner has id 9) so I need SQL to select the corresponding reservations.
Reservations with no partners (table 4) and/or guides (table 5) must be included.
All partners and guides must be included in the result (reservation can have more partners/guides)
All information in table 4 and 5 must be included (like the status from table 4).
A simplified version of the database:
Table 1: reservations:
id id_client id_tour
1 22 6
2 23 5
Table 2: clients (one reservation has one client):
id name
22 John
23 William
Table 3: tours (one reservation has one tour)
id name
5 big tour
6 small tour
Table 4: partners (one reservation can have multiple partners):
id id_reservation id_partner_type id_partner status
34 1 9 16 1
35 1 9 17 0
Table 5: guides (one reservation can have multiple guides):
id id_reservation id_guide
18 1 14
19 1 15
I have tried to work this out but I just can not get a query that does the job. I used GROUP_CONCAT to get the multiple partner and guide id's. Biggest problem I have is not being able to include the reservations that have no partners and/or guides like reservation 2.

To include all reservations that have no partners and guides you need to use OUTER JOINs, for example the following query will gives you all information from your tables 4, 5 including your condition:
Select p.*, g.*
from reservations r
left outer join partners p on p.id_reservation = r.id
left outer join guides g on g.id_reservation = r.id
where p.id_reservation is null and g.id_reservation is null

Related

Find next occurrence from a reference table sql

I have searched many other questions, but cant find a usable comparison. I have a SQL table that has a list of all the rooms at our hotel. I want to know the next time each room is going to be occupied. There are two tables I am looking at, one contains the name and details of each room we have, for all intents it is a static table. The other table is a reservations table that shows check in and check out times, and has a column that references which room is being used.
Table Rooms
unique id name
1 Room 3
2 Room 4
3 Suite 1
4 Suite 2
5 Suite 3
Table Reservations
unique id start date room id
1 12/4/16 3
2 12/4/16 4
3 12/6/16 3
4 12/12/16 3
5 12/14/16 2
6 12/20/16 2
This would return only 3 values:
2 12/20/16
3 12/4/16
4 12/4/16
If also possible I would like the make it so that if a reservation is not found a null value is returned, so ultimately, the return value would be
Room Next Occurrence
1 null
2 12/20/16
3 12/4/16
4 12/4/16
5 null
Is there a way of doing this without my current php hack that runs 200 sql queries?
Thanks so much!
You can use left join
select rooms.id, rooms.name, reservations.`start date`
from Rooms
left join reservations on reservations.`room id` = Rooms.id
order by rooms.id

Couting a Mysql Table

I have two Mysql tables which are:
1 - Main table (_benefits) which consists of benefitCode, benefitName and
2 - Second table which consists of clientID, benefitCode1, benefitCode2, etc.
what I need is that when I do a SELECT * FROM _benefits
I get a COUNT of all clients receiving the corresponding benefitCode
a small example would be:
Main Table
Benefit Code Benefit Name
6MBO 6 Monthly Bonus
AP Age Pension
Beneficiaries Table
clientID 6MBO AP
123M 1 0
456M 1 1
Required Output Select statement should give
Benefit Code Benefit Name Total
6MBO 6 Monthly Bonus 2
AP Age Pension 1
Thank you for your assistance

Query for extracting info from one table based on other

I have two tables post and share, post has many share. I want to fetch all data in post table using userId(posted by owner user) and also check share table using same userid that is if some one shared post to other user, if any condition is true, I need to fetch data.
I want to fetch data in post table if posted by owner or shared by other user in share table.
Example :
table name: post
id(pk) postname userid
1 abc 10
2 xxx 10
3 yyy 11
4 zzz 12
5 bbb 13
table name:share
id postid(fk) userid
1 3 10
2 4 10
3 3 11
4 1 12
Expected output: example find by userid 10
id postname userid
1 abc 10 // this record created by user 10 (owner)
2 xxx 10 // this record created by user 10 (owner)
3 yyy 11 // this record shared by other user to user 10.
4 zzz 12 // this record shared by other user to user 10.
You may want to print created_by and shared_by in two different columns as the example seems a bit confusing. Below query should produce the expected output in that case:
select p.id, p.postname, p.userid as 'created_by', s.user_id as 'shared_by'
from post p left outer join share s on p.id = s.postid
where p.userid = 10
order by p.id;
It finally clicked what you are looking for..
select p.id, p.postname, p.userid
from post p
join share s on s.postid=p.id
where s.userid='10' or p.userid='10'
That should return all interactions related to a specific user (id 10), either if a post was created by that user, or a post was shared to that user.

mySql one to many relation table structures

Folks can you please give your suggestions for my question regarding mysql joins.
My Table structures:
place table:
place_id place_name city
1 Hotel Golconda Hyderabad
2 Paradise Hotel Hyderabad
3 Hotel Mayuri Hyderabad
place_tags
tag_id tag_name
1 Valet Parking
2 Air Conditioned
3 Buffet
4 Bar
5 Family Dining
places_info Table:
place_id tag_id
1 1
1 2
1 3
2 1
2 5
3 1
3 4
The above is all my tables which are containing the place names and address in places table, all the facilities of the restaurants in tags table and mapping of the facilities of each place in places_info table.
Is this my table structures are correct to get the places which had "Valet parking and Buffet". How can write a join query for this type of results to get.
Most Importantly we had millions of places in places table and also in the places_info table. How to achieve maximum performance with this type of table structure? Or shall I need to change the table structures?
Please guide me.
This'd be the basic structure for "places with valet AND buffet":
SELECT place_id, COUNT(places_info) AS cnt
FROM place
LEFT JOIN places_info ON place.place_id = places_info.place_ID
AND tag_id IN (1, 3)
^^^^---- two tags: valet(1) + buffet(3)
GROUP BY place.place_id
HAVING cnt = 2
^^^---- must have both tags
For a places which have NEITHER of the tags, or only one, the count would come back 0, or 1, and get dumped by the HAVING clause.

Find all the leaf nodes below a subtree in a Tree structure in sql server

I've a tree structure, and its subsequent assignment table for customer categories in an sql server database.
CustomerCategory (CategoryID, ParentId)
CustomerInCategory(CustomerID, CategoryID)
If a CustomerCategory has any customer assigned to it, we can't add another subcategory to it. So, Customer can only be added to the lowest level in every sub tree. In other sense, the result of this query
SELECT * FROM `CustomerCategory` WHERE `CategoryId` NOT IN
(SELECT DISTINCT `parentid` FROM `CustomerCategory` WHERE `parentid` IS NOT NULL)
would yield leaf nodes. The Other thing is that, this tree might have subtrees of different levels, and we also, don't want to bound the number of levels in anyway, however, our users won't need more than 10 levels. Consider this as an illustration
CategoryID------ParentID---------------Name
1 NULL All Customers
2 1 Domestic
3 1 International
4 2 Independent Retailers
5 2 Chain Retailers
6 2 Whole Sellers
7 5 A-Mart
8 5 B-Mart
9 4 Grocery Stores
10 4 Restaurants
11 4 Cafes
CustomerID---------CustomerName----------Category
1 Int.Customer#1 3
2 Int.Customer#2 3
3 A-Mart.Branch#1 7
4 A-Mart.Branch#2 7
5 B-Mart.Branch#1 8
6 B-Mart.Branch#2 8
7 Grocery#1 9
8 Grocery#2 9
9 Grocery#3 9
10 Restaurant#1 10
11 Restaurant#2 10
12 Cafe#1 11
13 Wholeseller#1 6
14 Wholeseller#2 6
My requirement is something like this, "Given a node in Categories, Return All the Customers attached to any node below it".
How can I do it with sql?
Obviously this can be done with a recursive call in the code, but how can we do it in t-sql (without calling a stored procedure several times or using text-based search)?
Can any body, Use a CTE to solve this problem?
I have a result set of something like this in mind
CustomerID--------Customer Name----------------CategoryId----------CAtegoryName
12 Cafe#1 11 Cafes
12 Cafe#1 4 IndependentRetailers
12 Cafe#1 2 Demoestic
12 Cafe#1 1 AllCustomers
.
.
.
4 A-Mart.Branch#2 7 A-Mart
4 A-Mart.Branch#2 5 Chain Retailers
4 A-Mart.Branch#2 2 Domestic
4 A-Mart.Branch#2 1 All Customers
.
.
.
14 Wholeseller#2 6 WholeSellers
14 Wholeseller#2 2 Domestic
14 Wholeseller#2 1 All Customers
This is not necessarily a good Idea to layout a result like this, This would consume too much space, something that might not be required, yet, a search in such result set would be very fast. If I want to find all the customers below say categoryId = 2 , I would simply query
SELECT * FROM resultset where category ID = 2
Any suggestions to improve the data model is super welcomed! If It helps solving this problem.
Once again, I'm not fixated on this result set. Any other Suggestion that solves the problem,
"Given a node in Categories, Return All the Customers attached to any node below it", is well accepted.
You can use a CTE to recursively build a table containing all the parent-child relationships and use the where clause to get only the subtree you need (in my example, everyting under CategoryId 5) :
WITH CategorySubTree AS (
SELECT cc.CategoryId as SubTreeRoot,
cc.CategoryId
FROM CustomerCategory cc
UNION ALL
SELECT cst.SubTreeRoot, cc.CategoryId
FROM CustomerCategory cc
INNER JOIN CategorySubTree cst ON cst.CategoryId = cc.parentId
)
SELECT cst.CategoryId
FROM CategorySubTree cst
WHERE cst.SubTreeRoot = 5
You can modify this query to add whatever you need, for example, to get customers linked to the category nodes in the subtree :
WITH CategorySubTree AS (
SELECT cc.CategoryId as SubTreeRoot,
cc.CategoryId
FROM CustomerCategory cc
UNION ALL
SELECT cst.SubTreeRoot, cc.CategoryId
FROM CustomerCategory cc
INNER JOIN CategorySubTree cst ON cst.CategoryId = cc.parentId
)
SELECT cst.CategoryId,cic.CustomerId
FROM CategorySubTree cst
INNER JOIN CustomerInCategory cic ON cic.CategoryId = cst.CategoryId
WHERE cst.SubTreeRoot = 5
And of course you can join further tables to get labels and other needed information.