I have a customer table and an address table. Each customer can have multiple entries in the address table, but only one of those entries can be marked as 'primary'. I've put together the query to pull up the customer and their primary address as follows:
SELECT * FROM customers LEFT JOIN addresses
ON customers.cust_id = addresses.cust_id
WHERE customers.status = 1 AND addresses.primary = 1
I've found a flaw in that if the customer has not yet added an address to their account, they will not appear because there is no 'primary' address.
What's the best way to work around this?
SELECT *
FROM customers
LEFT JOIN addresses
ON customers.cust_id = addresses.cust_id
AND 1 = addresses.primary
WHERE customers.status = 1
Try modifying the query to AND (addresses.primary = 1 OR addresses.primary IS NULL)
Simply include the left side data when there is no address.
In the example below I use the primary field, but any field of the addesses table
is null in a left join clause when there is no matching key.
SELECT * FROM customers LEFT JOIN addresses
ON customers.cust_id = addresses.cust_id
WHERE customers.status = 1 AND
(addresses.primary = 1 OR addresses.primary IS Null)
Related
I have 2 tables: contracts_main_list and contracts_detail.
In contracts_main_list I have columns:
user_id
contract_id
and in contracts_detail:
contract_id
other columns with data
I need to select all the rows from the table contracts_main_list WHERE user_id = some number.
From these rows I need to get the list of contract numbers (from column contract_id) and according to them select rows corresponding to each of the contract number from the list. So something like:
WHERE contracts_detail.contract_id = contracts_main_list.contract_id
The contract_ids are probably gonna be unique, but in case there is some kind of error and there will be more rows with the same contract_id in either of the tables, I need to select only one row (so probably using DISTINCT) and select the latest record (both tables have a column id as a primary key)
Also if there is no row in contracts_detail matching with the contract_id to the contract_id of the first table contracts_main_list it should skip the row. But I guess the condition:
WHERE contracts_detail.contract_id = contracts_main_list.contract_id
already covers it.
I hope I made it clear enough. What I am trying to do in real life is show list of contracts with all the relevant data belonging to the user.
To sum this up, I need to find all the contracts belonging to the user and select the rows with details about each contract and finally get the data from the contracts_detail table as a result.
Here is the result you're looking for:
SELECT CD.*
FROM (SELECT C2.contract_id
,MAX(C2.id) AS last_main_list_id
,MAX(CD2.id) AS last_contracts_detail_id
FROM contracts_main_list C2
INNER JOIN contracts_detail CD2 ON CD2.contract_id = C2.contract_id
GROUP BY C2.contract_id) L
INNER JOIN contracts_main_list C ON C.id = L.last_main_list_id
AND C.user_id = ?
INNER JOIN contracts_detail CD ON CD.id= L.last_contracts_detail_id
This query use a subquery for the FROM because of the following indication you provided:
The contract_ids are probably gonna be unique, but in case there is
some kind of error and there will be more rows with the same
contract_id in either of the tables, I need to select only one row
If you're sure that the contract_id are unique, here is the same query without this check on contract_id:
SELECT CD.*
FROM contracts_main_list C
INNER JOIN contracts_detail CD ON CD.contract_id = C.contract_id
WHERE C.user_id = ?
Hope this will help you.
This is my company Table
CompanyID, CompanyName
This is my Contact Table
ContactID, ContactName, CompanyID
This is my Report Table
ReportID, ReportName
This is my ReportContact Table, Many to Many Relationship
ContactID, ReportID
I want to return all ALL my CONTACTID of 1 company, include those who are not assign to any report, I also want to return the reportID that are assign to different contacts
1 contacts can be assign to many reports
1 reports can consist of many contacts
My current SQL CODE only manage to get the 2 contactID in the ReportContactTable
SELECT rc.ContactID, rc.ReportID from contact c INNER JOIN Reportcontact rc on c.ContactID = rc.ContactID Where CompanyID=1
how can Return all the contact include those not in the reportcontact table, but get the reportID at the same times?
INNER JOIN filters out those rows that are not in ReportContact. Try to use LEFT JOIN if you want all contacts from contact table.
SELECT rc.ContactID, rc.ReportID
FROM contact c LEFT JOIN Reportcontact rc
ON c.ContactID = rc.ContactID
WHERE CompanyID = 1
I'm not 100% sure I understand what you are trying to do, but if you want all rows from the contact table then you need to use an OUTER rather than INNER join.
Try changing the word INNER to LEFT.
An INNER join ensures that rows that satisfy the join condition appear in both tables.
An OUTER join says "show me all the rows in one table, plus those that satisfy the join condition from the other table". Which table shows all the rows depends on the use of the keywords LEFT and right
a left join b on a.id = b.id will show all rows from table a plus those from b which satisfy the join condition
a right join b on a.id = b.id will show all rows from table b plus those from a which satisfy the join condition
I'm trying to select records from 3 tables using a JOIN which is working well but I now need to add some additional conditions to the SELECT which I can't figure out. My current select works like this:
SELECT user.*, address.*, state.* FROM user
LEFT JOIN address ON user.id = address.user_id
LEFT JOIN state ON user.id = state.user_id
Now, the address and state could have multiple records but both tables have a bit field to indicate that they are the primary record and that's the one I want to select. I have tried adding a WHERE address.state = b'1' to the statement but it only returns those records that have a primary record, what I would ideally like to do is select the top record from the address/state table sorted by the primary field so the primary will be selected if it exists but the next record will be selected if there is no primary.
How can I achieve this with MySQL 5?
Add the condition to your LEFT JOIN:
LEFT JOIN address ON ( user.id = address.user_id AND address.state = b'1' )
The left join will only return rows that match this criteria, but you will still get users without a primary address.
SELECT users.mail, users.name FROM members
LEFT JOIN users ON (users.uid = members.uid) WHERE members.group = 27
AND members.uid NOT IN (SELECT subgroup_members.uid FROM subgroup_members
LEFT JOIN subgroups ON (subgroups.id = subgroup_members.sid)
LEFT JOIN users on (users.uid = subgroup_members.uid) WHERE subgroups.oid = 27 AND subgroup_members.leader = 1)
This query returns all members of a group that are not leaders of a subgroup.
The members table shows which userid(uid) belong to a group(group), and the subgroup_members table shows which users belong to a subgroup(sid). Leadership is denoted by '1' in the leader column of the subgroup_members table.
I am trying to figure out how to return all members of a group that are not the only leader of a subgroup and I am pretty stumped right now.
So instead of subgroup_members.leader = 1 I need to determine if it's the only value
Look into using GROUP BY to isolate unique indices.
Documentation: https://dev.mysql.com/doc/refman/5.5/en/group-by-modifiers.html
I have 3 InnoDB tables: emails, websites and subscriptions.
emails table has id and email columns.
websites table has id and address columns.
subscriptions table has id, email_id and website_id columns.
What I'm tring to do is supply an email and return a table with columns address and subscribed. The former is a list of all the addresses in the websites table and the latter gets value 1 if the supplied email address has an occurence in the subscriptions table with website_id set to that website, or 0 otherwise. But I'm willing to retain all the websites even if the user is not found.
The point I'm stuck is where I should change the value of the virtual column subscribed from 0 to 1 when that email has that record.
Here's my query so far. Does anybody know how to do this?
SELECT `address`, "0" AS `subscribed`
/* 0 becomes 1 for the websites email has subscribed to */
FROM `websites` a
LEFT JOIN (
SELECT s.`website_id` FROM `subscriptions` s
RIGHT JOIN (
SELECT `id` AS `email_id` FROM `emails`
WHERE `email`='someone#mail.com' LIMIT 1) e
ON s.`email_id`=e.`email_id`) l
ON l.`website_id`=a.`id`
And here are the example outputs for the desired values for the subscribed column:
If email is not found in the emails table all the rows get value 0
If email is found in the emails table...
if it is not found in subscriptions table all the rows get value 0
if it is found in subscriptions table, the appropriate address rows get value 1
Let me know if I couldn't wxplain it well. Does anytbody know what I should alter in my query?
Thanks in advance.
SELECT w.address, CASE WHEN s.id IS NULL THEN 0 ELSE 1 END AS subscribed
FROM websites w
LEFT JOIN subscriptions s
INNER JOIN emails e
ON s.email_id = e.id
AND e.email = 'someone#mail.com'
ON w.id = s.website_id
You could also come up with the subscribed value this way, which is a bit more concise but also somewhat less obvious.
SELECT w.address, COALESCE(s.id/s.id, 0) AS subscribed
FROM websites w
LEFT JOIN subscriptions s
INNER JOIN emails e
ON s.email_id = e.id
AND e.email = 'someone#mail.com'
ON w.id = s.website_id