Joining 2 tables to query for missing entry - php

I currently have two tables, "tc_services" and "tc_users" which both have a "USER_ID" field and "BILLING_ID" field. I need to query these together, finding any results where...
A) "tc_services" does not have a "BILLING_ID"
B) "tc_users" does not contain a "USER_ID" that matches that of the coorelating "tc_services"
I am trying to put together a JOIN query statement such as the following but not able to figure it out so far. Any help would be appreciated!
SELECT *
FROM tc_services AS services
JOIN tc_users AS users
WHERE services.USER_ID NOT IN users.USER_ID AND services.BILLING_ID = '';

Something like:
SELECT SERVICE_ID, COUNT(users.USER_ID)
FROM tc_services AS services
LEFT JOIN tc_users AS users ON services.USER_ID = users.USER_ID
WHERE services.BILLING_ID = ''
GROUP BY services.SERVICE_ID HAVING COUNT(users.USER_ID) = 0

Second Edit after seeing your comment:
Just do
SELECT
*
FROM tc_services
WHERE tc_services.billing_id IS NULL AND
tc_services.user_id NOT IN (SELECT user_id FROM tc_users)
No joins needed
Edit:
After rereading your question, you might want an 'LEFT JOIN'
see this picture: http://i.stack.imgur.com/66zgg.png
So your query(s) would look something like
SELECT
*
FROM tc_users u
LEFT JOIN tc_services s ON a.user_id = s.user_id
WHERE s.billing_id IS NULL
which would give you the list of users that don't have a billing ID.
and then similar for the second question.
Original Answer:
Sounds like you might want to use a 'Union' rather than a 'Join'
Check out this related answer: What is the difference between JOIN and UNION?

Related

Is it possible with MySQL to generate a query to fetch from several tables even if one has no results?

I'm facing a problem here:
I'm building a forum, this forum has several tables and I'm trying to fetch the comments and user info in a single query.
So far, it should be easy, the problem is that I can't change the structure and with the following query I get a perfect result IF there is a like to the answer. If no one likes the answer it fails.
Select
mfr.mfr_forum_answers.id,
mfr.mfr_forum_answers.date_created,
mfr.mfr_forum_answers.last_updated,
mfr.mfr_forum_answers.content,
mfr.mfr_forum_answers.accepted,
mfr.mfr_forum_answers.user_id,
mfr.mfr_users.level,
mfr.mfr_users.avatar,
mfr.mfr_forum_likes.subject_id,
mfr.wp_users.ID As ID1,
mfr.mfr_forum_topics.user_id As owner_id,
(SELECT count(mfr.mfr_forum_likes.id) FROM mfr.mfr_forum_likes WHERE mfr.mfr_forum_likes.subject_id = :id AND mfr.mfr_forum_likes.type = 'answer') as likes,
(SELECT count(mfr.mfr_forum_likes.id) FROM mfr.mfr_forum_likes WHERE mfr.mfr_forum_likes.subject_id = :id AND makefitreal.mfr_forum_likes.type = 'answer' AND mfr.mfr_forum_likes.user_id = :sessionId ) as i_like,
mfr.wp_users.user_nicename
From
mfr.mfr_forum_likes Inner Join
mfr.mfr_forum_answers
On mfr.mfr_forum_answers.topic_id =
mfr.mfr_forum_likes.subject_id Inner Join
mfr.mfr_users
On mfr.mfr_forum_answers.user_id = mfr.mfr_users.id
Inner Join
mfr.wp_users
On mfr.mfr_users.id = mfr.wp_users.ID Inner Join
mfr.mfr_forum_topics
On mfr.mfr_forum_answers.topic_id = mfr.mfr_forum_topics.id
Where
mfr.mfr_forum_answers.topic_id = :id
And
mfr.mfr_forum_likes.type = 'answer'
So far as said it returns only if an answer has a like, I'm thinking on adding a add to the user who posts the answer by default but I'm trying to improve my skills by solving new issues.
If someone has a suggestion in how I could overcome the fact that if a table is empty, the query continues I'd be really thankfull.
Thanks in advance-
Pihh
Yes. What you are looking for are called left and right joins. According to the documentation, with a LEFT JOIN you still join two tables as normal but
If there is no matching row for the right table in the ON or USING part in a LEFT JOIN, a row with all columns set to NULL is used for the right table.
This means that you can try to join two tables, but if a row does not have any results it will still return the results from the first table. The same is true for a RIGHT JOIN only it works the opposite way: it will return results if the tabled being joined to has results, but the original table does not.
It looks like you have 3 tables for 3 relationships: there are answers, a user gives an answer, and an answer might or might not have like. To grab this data, I would suggest starting from your answers table, performing an INNER JOIN on your users table (assuming there are always users), and a LEFT JOIN on your likes table. Here is a simple example:
SELECT *
FROM answers
INNER JOIN users ON users.id = answers.user_id
LEFT JOIN likes ON likes.answer_id = answer.id
WHERE answers.id = :id
AND likes.type = 'answers'
Of course, if for some unknown reason you need to start from your likes table, then you'd have to RIGHT JOIN the other tables. I hope that gives you a good idea of how you'd make your query.

Limit LEFT JOIN results to 1 with flexible where clause

my query looks like that:
SELECT
count(users.id)
FROM users
LEFT JOIN mail_sender_jobs_actions ON mail_sender_jobs_actions.userID = users.id
LEFT JOIN table2 ON table2.userID = users.id
LEFT JOIN table3 ON table3.userID = users.id
WHERE {$flexibleWhereClause}
Now, the mail_sender_jobs_actions table CAN (doesnt need to return anything) return multiple entries. I dont want to group the results but still limit the returns of mail_sender_jobs_actions to 1 so I dont get duplicates... Otherwise the count wouldnt work properly.
Scraped the whole web and found nothing working for me as I want to keep the where clause flexible. Any solution?
EDIT
so to explain the situation. We have a table with users (users). We have a table with actions (mail_seder_jobs_actions). We have other tables related to that query which are not relevant (table1, table2, table3)
If a user does an action, an entry is being created in the actions table.
The where clause is flexible, meaning it is possible that somebody wants to only show users with a specific action.
It is also possible that an action is not relevant to the user, so this entry gets ignored.
With where criteria you have there is no point using left join, since the where criteria applies to the table on the right hand side, effectively turning the left join into an inner join.
Apparently yo do not use any columns from the right hand side table, so instead of using joins, I would use an exists subquery.
SELECT
1 as count,
users.email
FROM users
WHERE EXISTS (SELECT 1
FROM mail_sender_jobs_actions
WHERE mail_sender_jobs_actions.userID = users.id
AND mail_sender_jobs_actions.type = '1'
AND mail_sender_jobs_actions.jobID = '106'
AND {$flexibleWhereClause})
However, there is little point in having the count() because it will always return 1. If you want to count how many records each user has in the mail_sender_jobs_actions table, then you have to use left join, group by, and move the where criteria into the join condition:
SELECT
count(mail_sender_jobs_actions.userID),
users.email
FROM users
LEFT JOIN mail_sender_jobs_actions ON mail_sender_jobs_actions.userID = users.id
AND mail_sender_jobs_actions.type = '1'
AND mail_sender_jobs_actions.jobID = '106'
AND {$flexibleWhereClause}
GROUP BY users.email

query user group hide search results

Hi I am trying to change some code so that users with certain group id do not show in search results.
at the moment the code is
$query = 'SELECT distinct b.'.$db->nameQuote('id')
.' FROM '.$db->nameQuote('#__users').' b';
I am trying to add something like the following but cannot get it to work.
select * from '.$db->quoteName('#__users').' where id not in (select user_id from #__user_usergroup_map where group_id = 8)
Any help would be appreciated.
Thanks.
This how you can try
select * from users u
where
not exists
(
select 1
from user_group ug
where
u.id = ug.iduser
AND ug.group_id = 8
)
You need change the table name and field name in the above query as your need.
DEMO
There are three ways of doing that.
Method 1: Join
Join usergroup_map table and then, select all rows that have different group_id that way:
SELECT <comma separated fields> from USERS u
LEFT JOIN USERGROUPS ug ON u.user_id = ug.user_id
WHERE ug.group_id != :group_id
GROUP BY u.user_id
And then -> bind any number to :group_id.
Please keep in mind that above statement will return users that are assigned to :group_id only if they are in another groups as well. (one to many relation).
Method 2: Subselect
Already suggested by other users.
Method 3: Join & Subselect
The 3rd, and the last option is to use sub-query within join statement, which tends to be the fastest solution in terms of optimalization. Of course, query times may be different depending on the engine you are working with, but it's worth giving a try.
SELECT <comma separated fields>
FROM USERS u
INNER JOIN (
SELECT g.user_id
FROM USERGROUPS g
WHERE g.group_id != :group_id
) ug ON ug.user_id = u.user_id
--
In this answer, I assume that you have properly configured database with foreign keys.

How to transfer a lot of values beteen tables in a variable or array?

I have two SQL tables. The first one structure is simple.
ID Name
----------
The second one is simple too.
CommentID Comment CreatorID
----------------------------------
I want to show in my site all the comments that correspond with the "ID of user"
The problem is we have here a lot of ID and two different tables.
Something like this:
$1= $bdd->query("SELECT * FROM comments WHERE id_user=220281");
$2=$1->fetch();
But its impossible because id user is not on the comments table.
The most simple way to do this is to join the tables like this:
select
users.name,
comms.commentID,
comms.comment
from
userTable users
join commentTable comms
on users.ID=comms.ownersID
where
users.id=1
This will return the users name in each row of data, but you don't need to use it in the output more than once.
It also sounds like you could use a few pointers on SQL queries. Do yourself a favour and have a read of this article I put together a while back.
SELECT c.*
FROM comments c
INNER JOIN users u ON c.id_creator = u.id_user AND
u.id_user = 220281
A simple join will do the trick like this :
SELECT c.comment, u.user_name FROM
Users u
JOIN
Comments c ON
c.creator_id = u.user_id
WHERE
u.user_id=220281
fiddle:http://sqlfiddle.com/#!6/3b28a/1

php/mysql join syntax

I have the userids of people who have joined a group in one table but not their names thatlie in another table. So I think I need to do a join. I'm starting with groupid that describes the grouop.
Table 1, groupmem has groupid and userid for the members.
Table 2, users has userid and username
The users table has every user. The groupmem only has some who have joined groups.
SQL statement should be something like following but can't get it to work.
select users.name
FROM users,groupmem
LEFT JOIN users
on groupmem.userid=users.userid
WHERE groupmem.groupid = 22
22 being some value..
Thinking maybe where clause is in wrong place or I am using wrong type of join but or not using on correctly but, in any case, can't get it to work. Thx for any suggestions:
Try:
SELECT u.username
FROM `users` u
LEFT JOIN `groupmem` g
ON u.userid = g.userid
WHERE g.groupid = 22
This should do the trick:
SELECT users.name
FROM groupmem
LEFT JOIN users ON groupmem.userid = users.userid
WHERE groupmem.groupid = 22
Your query seems to be quite right - assuming I guessed your table-structure right.

Categories