understanding how mysql joins work - php

i am having an bit of trouble understanding JOINS with mysql.
i have 3 tables.
gold_sended) user_id | sended
register) user_id | gold_swap_id
google_users) oauth_uid | portal_name
now what needs to be done is as follow.
first i need all the portal_names of google_users where oauth_id = the same as register.user_id
Next thing is i also need to check if the register.user_id = gold_sended.user_id
If the user_id from register is the same als gold_sended user_id then display
the portal name. If not then display nothing.
I never have worked with joins so i am an bit lost on how to do it propperly.
Ok its now solved.
SELECT
google_users.portal_name,
gold_sended.user_id,
gold_sended.date,
COUNT(gold_sended) as total_runs
FROM
register_gold_swap
LEFT JOIN google_users on register_gold_swap.user_id=google_users.oauth_uid
LEFT JOIN gold_sended on register_gold_swap.user_id=gold_sended.user_id
WHERE
register_gold_swap.gold_swap_id = "1"
AND register_gold_swap.status = "1"
GROUP BY google_users.portal_name
Is now outputting the correct data. Thank you all

select
g.portal_name
from
gold_sended as gs
left join register as r
on g.oauth_id=r.user_id
left join google_users as g
on gs.user_id=g.oauth_id
try this

Related

how to show a selected data in a single row?

I want to display a set of data in a single row, but I don't seem to implement it, I tried several ways, it still doesn't work. I want to display all permission names assigned for a role name in a single row.
for example :
| editor | edit-user, delete-user, delete-role |
| deleter | delete-user |
here's my sql
$datas = DB::SELECT(' SELECT roles.id, roles.name as roleName, permissions.name as PermName
FROM roles
LEFT JOIN role_has_permissions
ON (roles.id = role_has_permissions.role_id)
LEFT JOIN permissions
ON (role_has_permissions.permission_id = permissions.id)
ORDER BY roles.id');
thank you in advance :)
Can you join the two middle joins in a subquery:
LEFT JOIN (
SELECT
permissions.name as PermName
,role_has_permissions.role_id
FROM role_has_permissions
LEFT JOIN permissions ON role_has_permissions.permission_id = permissions.id)
ON roles.id = role_has_permissions.role_id

MY SQL Query for salary sheet

I have 3 tables in MYSQL From 2 different database running in same server
and my expected Output is
MY attempt of query is
SELECT `biometric`.`Empid`,
,`name`,`location`,`basic`,`hra`,`conveyance`,`total salary`,sum(DISTINCT DATEDIFF(LEAST(`endDate`,'$monthEnd' ),GREATEST(`startdate`,'$monthStart'))+1) as leaves FROM `biometric`.`biometric`,`biometric`.`employee` JOIN `lms`.`leaves` WHERE `biometric`.`empid`= `employee`.`empid` AND `employee`.`empid` = `leaves`.`id` AND
`startdate`<='$monthEnd' AND `endDate`>= '$monthStart' AND `leaves`.`status` = '3'
GROUP BY `Empid`
and here status =3 is approved leave and 1 is non approved leave.
and my out put coming is
Thanks in Advance...
You can try below query, even I did not test it so if you get any error then you can create an sqlfiddle so that I can correct it.
Basic concept is that you need to use left join for lms.leaves table as you need all employee details even they did not took leave under status 3.
SELECT bmt.`Empid`,`name`,`location`,`basic`,`hra`,`conveyance`,`total salary`,
IFNULL(SUM(DISTINCT DATEDIFF(LEAST(`endDate`,'$monthEnd' ),GREATEST(`startdate`,'$monthStart'))+1),0) AS LEAVES
FROM BM.`biometric` AS bmt
JOIN BM.`employee` AS emp ON bmt.`empid`= emp.`empid`
LEFT JOIN `lms`.`leaves` AS lvs ON emp.`empid` = lvs.`id` AND lvs.`status` = '3' AND `startdate`<='$monthEnd' AND `endDate`>= '$monthStart'
GROUP BY bmt.`Empid`;

MySQL Query, get user_ID then get Restaurant_ID then get restaurantName from 3 tables that match email at user table

I'm new to MySQL and I'm having problem with JOIN. Please give me some hint on how to achieve what I need.
My Table:
"user" table:
- user_id
- user_name
- user_email
"favouriteRestaurant" table:
- favrst_id
- user_id
- rst_id
"restaurant" table:
- rst_id
- rst_name
- rst_city
- rst_cuisine
- rst_phone
- rst_latitude
- rst_longitude
My query process:
Get user_id "WHERE" user_email match provided email address.
Use the user_id to query "favouriteRestaurant", if data available.
Get rst_name of matching rst_id from "favouriteRestaurant" table.
The final data I need is:
favrst_id
rst_id
rst_name
rst_city
rst_cuisine
rst_phone
rst_latitude
rst_longitude
I hope my explanation is clear enough. If it's not clear please ask/comment. Thank you very much.
The following is the actual SQL (above table are simplified) I've tried so far but the result is definitely not what I wanted. It give me all restaurant instead of matching in favRst.
SELECT
user.email,
user.user_id,
favourite_rst.restaurant_id,
favourite_rst.restaurant_id,
favourite_rst.user_id,
restaurant.name
FROM
user,
favourite_rst,
restaurant
WHERE
(user.email = 'user#abc.com')
You can also try this:
SELECT FR.favrst_id, FR.rst_id, R.rst_name, R.rst_city,
R.rst_cuisine, R.rst_phone, R.rst_latitude, R.rst_longitude
FROM user U,
favouriteRestaurant FR,
restaurant R
WHERE U.user_email = "aaaa#example.com"
and U.user_id = FR.user_id
and FR.rst_id = R.rst_id
and compare the execution time using inner join and without using inner join.
Try with this :
SELECT favrst_id, FR.rst_id, rst_name, rst_city,
rst_cuisine, rst_phone, rst_latitude, rst_longitude
FROM user U
INNER JOIN favouriteRestaurant FR ON U.user_id = FR.user_id
INNER JOIN restaurant R ON FR.rst_id = R.rst_id
WHERE user_email = "%$email%"
Hope it helps you
SELECT r.* , fr.favrst_id FROM restaurant r LEFT JOIN favourite_rst fr ON r.rst_id = fr.rst_id LEFT JOIN user u ON fr.user_id = u.user_id WHERE u.user_email = "abc#example.com"

SQL Advice - selecting multiple rows from a table as an innerJoin

I've been working on a project that until now has only needed to find 1 row from the joined table. But now I need to grab multiple rows..
So as it stand my sql works something like:
Select rows for each company for this particular project which alone would find company details (name, id, telephone.. blah).
Then I join a table that contains form data submitted for each company (multiple forms - so multiple records)
Until now i have been specifying one formid to look for in the join, but now i need to specify multiple ones.
If I use WHERE form_id = 1 OR form_id = 2 OR form_id = 3 ... I get a result of only the first form match that is found per company..
If I mix up the query so it looks for the forms 1st and returns multiple records for each company with different form data - that works in this sense..
But I am then looping through this array in a view and creating a table row per record (previously each row was a new company) but using the latter would cause multiple records to show for the same company.
Any way I can do this? I tried group by with the latter method but this results in only 1 record again.
SELECT DISTINCT p.project_company_has_user_id, p.project_company_has_user_project_id, p.project_company_has_user_user_id, c.company_id, c.company_hall_no, c.company_company_name, c.company_type, c.company_country, c.company_stand_number, c.company_image_file_1, p2.project_id, p2.project_name, u.user_id, u.user_username, o.orders_id, o2.order_detail_id, o2.order_detail_product_id, f2.form_question_has_answer_id, f2.form_question_has_answer_request, f2.form_question_has_answer_form_id, f2.form_question_has_answer_user_id
FROM project_company_has_user p
INNER JOIN company c ON p.project_company_has_user_company_id = c.company_id
INNER JOIN project p2 ON p.project_company_has_user_project_id = p2.project_id
INNER JOIN user u ON p.project_company_has_user_user_id = u.user_id
INNER JOIN form f ON p.project_company_has_user_project_id = f.form_project_id
LEFT JOIN orders o ON p.project_company_has_user_user_id = o.orders_user_id
LEFT JOIN order_detail o2 ON ((o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
LEFT JOIN form_question_has_answer f2 ON ((f2.form_question_has_answer_form_id = 297 AND f2.form_question_has_answer_user_id = p.project_company_has_user_user_id))
WHERE (f.form_template_name = "custom" AND p.project_company_has_user_garbage_collection = 0 AND p.project_company_has_user_project_id = 48) AND (LCASE(c.company_country) LIKE "%uk%" OR LCASE(c.company_country) LIKE "%uk%") ORDER BY company_company_name asc
you need another field in order_detail as o2 . this field is row_index(position),etc for positioning record
LEFT JOIN order_detail o2 ON (o2.row_index=1 AND (o2.order_detail_orders_id = o.orders_id AND (o2.order_detail_product_id = 65 OR o2.order_detail_product_id = 68 OR o2.order_detail_product_id = 64)))
Personally I would use an Outer Join for the table of which elements you need to list all matches. Should you them need to clean up that data you can build the logic into the Join Condition (as step 2). Depending on the volume of data you are handling and whether or not you need to reuse it later in the same proc, you may want to post that primary dataset into a temp table and use that as source (primary) for your later logic.
Hope that helps. If you need the code, let me know, but it is pretty straight forward.
Regards
Mac

Join tables with comma values

I have a hard nut to crack with joing 3 tables.
I have a newsletter_items, newsletter_fields and newsletter_mailgroups which I want to be joined to get a list of newsletters.
The newsletter_items contains the fields:
letter_id, letter_date, receivers, template, status
That can look like
1, 1234567899, 1,2 (comma separated), standard.html, 1
newsletter_fields contains the fields:
field_uid, field_name, field_content, field_letter_uid
That can look like
1, letter_headline, A great headline, 1
where field_letter_uid is the newsletter for which the field belongs to.
and newsletter_mailgroups contains the fields:
mailgroup_id, mailgroup_name, number_of_members
That can look like
1, Group1, 233
2, Group2, 124
3, Group3, 54
What I want is to combine these 3 tables to that I can get a list of all the newsletter like this:
Letter date | Letter headline | Receivers | Status
2008-01-01 12:00:00 | A great headline | Group1, Group 2 | 1
So in short I want my SQL query to join the 3 tables and in that process select the receivers from the mailgroup table and display them comma separated like Group1, Group 2
This what I got now
SELECT A.*, B.* FROM newsletter_items A, newsletter_fields B, WHERE B.field_letter_uid = A.letter_id AND field_name = 'letter_headline' AND A.template = '". $template ."';
But I can't seem to figure out how to get the mailgroups into that.
I recommend that you make your joins explicit.
It makes it easier to debug your query and to change inner with left joins.
There is absolutely never a good reason to use SQL '89 implicit join syntax.
SELECT ni.*
, nf.*
, group_concat(nm.mailgroup_name) as mailgroups
FROM newsletter_items ni
INNER JOIN newsletter_fields nf
ON (nf.field_letter_uid = ni.letter_id)
INNER JOIN newsletter_mailgroups nm
ON (find_in_set(nm.mailgroup_id, ni.receivers))
WHERE
nf.field_name = 'letter_headline'
ni.template = '". $template ."'
GROUP BY ni.letter_id;
Regarding your database design.
I recommend you normalize your database, that means that you move the comma separated fields into a different table.
So you make a table receivers
Receivers
----------
id integer auto_increment primary key
letter_id integer not null foreign key references newsletter_items(letter_id)
value integer not null
You then remove the field receiver from the table newsletter_items
Your query then changes into:
SELECT ni.*
, group_concat(r.value) as receivers
, nf.*
, group_concat(nm.mailgroup_name) as mailgroups
FROM newsletter_items ni
INNER JOIN newsletter_fields nf
ON (nf.field_letter_uid = ni.letter_id)
INNER JOIN newsletter_mailgroups nm
ON (find_in_set(nm.mailgroup_id, ni.receivers))
LEFT JOIN receiver r ON (r.letter_id = ni.letter_id)
WHERE
nf.field_name = 'letter_headline'
ni.template = '". $template ."'
GROUP BY ni.letter_id;
This change should also speed up your query significantly.
If it's allowed, why don't you create a new table called newsletter_item_receivers where you could store letter_id, receiver_id fields?
Having comma separated values in a field like this usually means you're missing a table :)
Edit:
By using CSV, you are making your life miserable when you want to retrieve an answer to "give me all newsletters that receiver_id=5 receives" :)
Here's a good answer to a similar question on SO: Comma separated values in a database field
Edit2:
If I understand your table relationships correctly then it would be something like this:
SELECT
a.letter_date,
b.receiver_id,
a.status
FROM newsletter_items_receivers b
LEFT OUTER JOIN newsletter_items a ON (a.letter_id = b.letter_id)
LEFT OUTER JOIN newsletter_mailgroups m ON (m.mailgroup_id = b.receiver_id)
NOTE! This query WILL NOT return a newsletter when there are no receivers of that newsletter.
If you need that functionality you can try something like this:
SELECT
x.letter_date,
y.mailgroup_name,
x.status
FROM (
SELECT
a.letter_date,
b.receiver_id,
a.status
FROM newsletter_items a
LEFT OUTER JOIN newsletter_items_rec b ON (b.letter_id = a.letter_id)) x
LEFT OUTER JOIN newsletter_mailgroups y ON (y.mailgroup_id = x.receiver_id)
I don't have access to SQL right now so I might have made some syntax errors (hopefully not logical ones :)).
As for why we are doing it like this, as #Konerak pointed out, you'd be well advised to read up on database normalization and why it's important.
You can start with this article from about.com, just glanced over it seems an OK read
http://databases.about.com/od/specificproducts/a/normalization.htm
Also, it would be good if you'd keep fields names the same across multiple tables.
For example you have letter_id in newsletter_items, but you have field_letter_uid in newsletter_fields. Just a thought :)
Try to use
SELECT A.*, B.*, group_concat(C.mailgroup_name SEPARATOR ',')
FROM newsletter_items A, newsletter_fields B, newsletter_mailgroups C
WHERE B.field_letter_uid = A.letter_id
AND field_name = 'letter_headline'
AND A.template = '". $template ."'
and find_in_set(c.mailgroup_id, A.receivers)
group by A.letter_id;

Categories