Distinct select statement using two tables - mysql

I've looked around the forum for a while now, but I can't find a solution for the following.
I've got two tables, users and bookings.
users:
unique id, firstname and lastname
bookings:
uniquide id, userId, arrival and departure
For every booking a user makes, the bookings table will contain the unique users id in the field userId.
I now want to get the firstname and lastname from table users, and all bookings which are made depending on the userId.
select users.*, bookings.* FROM users, bookings WHERE bookings.userId =:id GROUP BY bookings.id
The statement above returns all bookings according to the userId, but it also contains the user itself multiple times, i just need the user data once.

select u.id, u.firstname, u.lastname, b.id as bookingid, b.arrival, b.departure from users u JOIN bookings b ON u.id = b.userid
doing GROUP BY on booking.id makes no sense in this case, as booking.id is the lowest level element. Now, you could group by users.id, but then you can no longer return all the individual bookings - but you can return a lot of helpful things like COUNT(bookings.id) AS NbrBookings or MIN(arrival) or MAX(departure)
but you can't have aggregate data and inidividual data at the same time.

users.*, bookings.*
instead of this specify the relevant column names

Related

Finding Values of same ID from different table

I have 2 tables:
1.Users (This table contains all the information of users like name, Userid, mobileno)
2.Transaction (This table contains the information of all the transaction of a user)
But the UserID is same in both the tables
I have some filter conditions like:
[ TransactionType=1 AND status=1 and (RealCash>0 or Bonus>0 or Winning>0)] which i want to apply on Transaction table
once I applied the condition i will have some UserID
Now i want that the information of the users from the Users table that have the same UserID which i've obtained from above from the transaction table
How can i do that in MYSQL ?
use JOIN : https://www.mysqltutorial.org/mysql-join/
For example:
SELECT
u.name,
u.Userid,
u.mobileno,
t.TransactionType
FROM
Users u
INNER JOIN Transaction t ON t.Userid = c.Userid
WHERE t.TransactionType=1 AND t.status=1 and (t.RealCash>0 or t.Bonus>0 or t.Winning>0)
But read carefully about other join types (left, right, cross) as you may get different results.
SELECT
name, Userid, mobileno
FROM
Users
WHERE
UserID IN (SELECT
UserID
FROM
Transaction
WHERE
TransactionType=1 AND status=1 and (RealCash>0 or Bonus>0 or Winning>0);

How can I get customer data based on the number of users they have?

I want to get customer data from all the businesses with more than 1 user.
For this I think I need a subquery to count more than 1 user and then the outer query to give me their emails.
I have tried subqueries in the WHERE and HAVING clause
SELECT u.mail
FROM users u
WHERE count IN (
SELECT count (u.id_business)
FROM businesses b
INNER JOIN users u ON b.id = u.id_business
GROUP BY b.id, u.id_business
HAVING COUNT (u.id_business) >= 2
)
I believe that you do not need a subquery, everything can be achieved in a joined aggregate query with a HAVING clause, like :
SELECT u.mail
FROM users u
INNER JOIN businesses b on b.id = u.id_business
GROUP BY u.id, u.email
HAVING COUNT (*) >= 2
NB : in case several users may have the same email, I have added the primary key of users to the GROUP BY clause (I assumed that the pk is called id) : you may remove this if email is a unique field in users.

Joining tables in MySQL and requesting data from second table only

I'm trying to join 2 tables where I need to show only 3 columns from the second one where another column is used as a comparison.
For example:
Table one is called employee: it has a column called user_id and some other columns
Table two is called people: it has a column called user_id which included some of the employees user_ids
The columns I want to select are all from table people! (firstname, lastname, email)
I tried the following but something going wrong:
SELECT userid, firstname, lastname, email
FROM people
JOIN employee
WHERE people.userid = employee.userid;
I'm not sure what am I doing wrong, could you please help me correct it?
You can try this query:
SELECT
p.userid,
p.firstname,
p.lastname,
p.email
FROM
people as p,
employee as emp
WHERE
p.userid = emp.userid
Looking at your script, it looks like you'll run into ambiguous columns in at least your userid. You want to explicitly tell SQL where the column comes from like in your WHERE clause if there are columns sharing the same name between the two tables.
SELECT
userid, -- AMBIGUOUS
firstname,
lastname,
email
FROM people
JOIN employee
WHERE people.userid = employee.userid;
Example solution:
SELECT
people.userid,
people.firstname,
people.lastname,
people.email
FROM people
JOIN employee
WHERE people.userid = employee.userid;
For this issue you can use this query
let suppose that I have a users table where a user have zero to one profile picture
I need the user (Name,LastName,BirthDate) for users who have no profile picture
I can use this query
select *
from user c
where NOT EXISTS (
select 1
from photo p
where p.id = c.photo_id
)
in this where you can use any field between this two table
removing the not will result on the users who have a profile picture
hope this help you
you can search for SEMI JOIN and ANTI JOIN for more informations
i think this query will solve your problem
insert into table1 (clmn_1,clmn_2,clmn_3) SELECT clmn_1,clmn_2,clmn_3 FROM table2 where id = value

Better MySQL query?

Here's one example, I have a Car, User, Member, and Dealer tables. At the moment I'm trying to get the name of a dealer who owns a car by matching their userids up
Select userid, name FROM `User` WHERE userid IN
(SELECT userid FROM 'Car' WHERE userid in
(SELECT userid FROM `Member` WHERE userid IN
(SELECT userid FROM `Dealer`)))
This does what I want but I can't help feel there's a better way of doing it? Currently the userid in Car is a FK of the userid in Dealer which is a FK of the userid in Member which is a FK of the userid in User which stores the name.
Can I go straight to getting all the userid's and names of dealers who's id is in the Car table, whilst making sure they're actually a Dealer?
Basically your schema is a downstream schema
Users -> Members -> Dealer -> Car
Good thing is you made all the possible keys that you need here.
So to selct anything in any table just go down stream from Users for example for the data you want
Select * from `USER` u
where
dealer.user_id = car.user_id and
member.user_id = dealer.user_id and
u.user_id = member.user_id
The reason i went upstream in matching records is because we want to make as few matching operations as possible. As you can see user table is supposed to contain the maximum records. So i match with car table and get all the user_id where there is a match in dealer. similarly i go from dealer to member and then to user. this means all the records of users will be matched with a lot fewer records that they would have been if i went from users to members to dealer to car.
But this is not fool proof solution. it will depend on your data. because it may be a case where one user may have multiple cars, then it would be better to go downstream.
Use JOIN instead of subqueries to fetch the data.
Try this:
SELECT U.userid, U.NAME
FROM `User` U
INNER JOIN Car C ON U.userid = C.userid
INNER JOIN Member M ON C.userid = M.userid
INNER JOIN Dealer D ON M.userid = D.userid;

"Join" admins of different tables into a string

The real issue
Involved tables and their columns
accounts [id,name]
rooms [id,name,topic,owner]
room_admins [account_id,room_id]
Q: Get all rooms with their admin- and owner ids.
Where "all" of course has a condition to it (above: WHERE name LIKE ...)
Admins and owners should be returned in one column just called "admins". I tried to concatenate them above into one string.
What I tried
I came up with a solution, but it requires the use of an omnious external variable ":room_id" that changes on each outer SELECT and makes therefore no sense at all.
SELECT id,name,topic,
(SELECT GROUP_CONCAT(admins.account_id) AS owner
FROM
(SELECT account_id
FROM `room_admins`
WHERE room_id=:room_id
UNION
SELECT owner FROM `rooms` WHERE id=:room_id) admins) AS owner
FROM `rooms`
WHERE name LIKE "%htm%" OR topic LIKE "%htm%" LIMIT 20
Well, I haven't given this a deep thought... but I've just came up with this (sample data would have been useful to make tests... so this is just a blind answer).
select id, name, topic, group_concat(owner_admin) from (
select id, name, topic, owner owner_admin from rooms
union
select id, name, topic, account_id from rooms
left join room_admins on id = room_id
) s
where name like "%htm%" or topic like "%htm%"
group by id, name, topic
Basically I'm just generating a derived table with owner and admins mixed in one column. Then performing the grouping on that mixed column.
Most of the times, when you want to select and display dependent data, you want to use a JOIN. In this case, you want to join the rooms with their admins, so basically:
SELECT r.id, r.name, r.topic, a.id
FROM rooms r
LEFT JOIN admins a
ON r.id = a.room_id
WHERE :condition
Since you have one additional admin not in the admins table (the room owner), you have to (self) join a second time:
SELECT r.id, r.name, r.topic, a.id
FROM rooms r
LEFT JOIN admins a
ON r.id = a.room_id
LEFT JOIN rooms o
ON r.id = o.id
WHERE :condition
This doesn't give us any new information, but your question states that you want to return the list of admins in a single field. So, finally, putting it all together:
SELECT r.id, r.name, r.topic, GROUP_CONCAT(a.id)
FROM rooms r
LEFT JOIN
(
SELECT id, room_id FROM admins
UNION SELECT room.owner AS id, rooms.id AS room_id FROM rooms
) a
ON r.id = a.room_id
WHERE :condition
GROUP BY r.id
But to avoid this ugly sub-select-union clause, I'd advise you to put the room owner into your admin table too.