I have these four tables:
table offers
id
id_company
description
table companies
id
name
table company_customer
id_company
id_customer
table customers
id
name
I need to get the offers, the company that has the offer and also the customers which have a relation with those companies. It's quite simple.
The query I'm typing is the following:
SELECT c.name, c.description, cu.name cu_name
FROM companies c
INNER JOIN offers o ON o.id_company = c.id
INNER JOIN company_customer cc ON cc.id_company = c.id
INNER JOIN customers cu ON cu.id = cc.id_customer
WHERE o.id_company = 1
ORDER BY o.id_company;
The "problem" is that sometimes an offer of a company is available for diferent customers.
Let me to show you the problem with a real example:
'Ebay' | 'offer number 1' | 'customer 1'
'Ebay' | 'offer number 1' | 'customer 2'
But I need concatenate or show both rows on a single row (just in the cases that company and the offer is the same but the customers are different). In other words, I need the following result:
'Ebay' | 'offer number 1' | 'customer 1, customer 2'
I work with PHP and MySQL. I know this may be done with PHP but I'm wondering if it could be possible to do it just with MySQL.
Any ideas??
Any help would be really appreciated. My apologize for my english level. I know it's not my best.
Thanks in advance for your time and attention.
You need to group by both company and offer, so you want this query:
SELECT
c.`name` AS companyName,
o.description AS offerName,
GROUP_CONCAT(cs.`name` ORDER BY cs.id) AS customerNames
FROM
companies c
INNER JOIN offers o ON o.id_company = c.id
INNER JOIN company_customer cc ON cc.id_company = c.id
INNER JOIN customers cs ON cs.id = cc.id_customer
WHERE
c.id = 1
GROUP BY
c.`name`,
o.description
Amyway there is no relation between offers and customers in your database, so you might consider to add such. Otherwhise all company's customers will appear in each offer of this company:
+-------------+-----------+----------------------------------+
| companyName | offerName | customerNames |
+-------------+-----------+----------------------------------+
| Ebay | Offer 1 | Customer 1,Customer 2,Customer 3 |
| Ebay | Offer 2 | Customer 1,Customer 2,Customer 3 |
+-------------+-----------+----------------------------------+
2 rows in set
But if you want exacly that, everything is OK then.
You can use a the aggregated GROUP_CONCAT Function
SELECT c.name, c.description, GROUP_CONCAT(string SEPARATOR ',')
FROM <<table And Joins...>>
GROUP BY c.name, c.description;
See hier http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
There is no way to represent this in your current table design, because an offer can reference (at most) one company. To do what you wish, you will need to add an offer_company table with id_company and id_offer, and remove the id_company field from the offer table. Then you will add an additional join column to your query, and a group by clause to group the rows with the same offer together.
Once you have the rows grouped together, you can merge them into a single row, concatenating the customer information, in your php code.
Related
I need to join two tables, and each must have a common relationship.
One table is for "purchases" and another for "payments", both are directly related to the "customers" table.
I tried that, but it is not working.
SELECT c.id AS idclient, c.name AS nameclient, p.id AS idpayment, cp.id AS idpurchases
FROM clients AS c
RIGHT JOIN payments AS p ON c.id = p.client
RIGHT JOIN purchases AS cp ON c.id = cp.client
The tables have different structures and other fields that are not currently needed. The fields are basically the ones that are in the select.
Expected outcome:
When a customer is NOT listed in the "purchases" or "payments" tables, it should not be listed, with the exception of a Boolean clause in the "purchases" table (company business rule).
idclient | nameclient | idpurchases | idpayment
109 | John | 3 | NULL
27 | Code | 1 | 1
302 | Woen | 4 | NULL
NULL | NULL | 2 | NULL
You want to join the three tables, but only show clients that have an entry in at least one of the tables payments and purchases. So outer join these tables and use a where clause to ensure at least one of them has a match.
SELECT c.id AS idclient, c.name AS nameclient, p.id AS idpayment, cp.id AS idpurchases
FROM clients AS c
LEFT JOIN payments AS p ON p.client = c.id
LEFT JOIN purchases AS cp ON cp.client = c.id
WHERE (p.client IS NOT NULL OR cp.client IS NOT NULL);
This is a strange query, however, because the table design suggests there can be multiple payments and multiple purchases per client, but your query combines each payment with each purchase a client made. Aren't they somehow related? Would a client make a payment without having purchased anything? What I am saying is, while you asked for this query, you may really want a completely different one.
As far as i see you need LEFT JOIN.
Meaning you have clients with no purchases and no payments.
Or the client is doing the purchase but still didn't pay
There are no purchase and no payments with out an client !
SELECT c.id AS idclient, c.name AS nameclient,
p.id AS idpayment,
cp.id AS idpurchases
FROM clients AS c
LEFT JOIN payments AS p ON c.id = p.client
LEFT JOIN purchases AS cp ON c.id = cp.client
Possible output
[idclient,name, idpay,idPur]
[1,A,2,3] - ok
[2,B,null,4] - no payment :ok
[3,C,null,null] - no purchase and no payment : ok
or
use JOIN(inner) to get without null [1,A,2,3]
SELECT c.id AS idclient, c.name AS nameclient,
p.id AS idpayment,
cp.id AS idpurchases
FROM purchases AS cp
//left if wanted all record
//inner : now only all columns populated
JOIN payments AS p ON cp.client = p.client
JOIN clients AS c ON c.id = cp.client
I want to work on SQL. inner join is not working missing. I am using two tables get data on "city_id " field these table code so please help me
inventory
==========================================
inventory_id | city_id | title |is_enabled
==========================================
1 | 1 | abc | 1
2 | 1 | bcd | 1
cities
====================================
city_id | city | title
===================================
1 | delhi | abc
2 | nodia | bcd
SELECT * FROM inventory i
INNER JOIN cities c
ON i.city_id = c.city_id
WHERE i.is_enabled = 1
ORDER BY i.inventory_id DESC LIMIT 10;
Some databases (such as MS Access and MySQL) do not support FULL OUTER JOIN.
However, FULL OUTER JOIN is rarely needed -- and almost never when you are using keys defined between tables. Well structured databases have keys with appropriate values.
I suspect an INNER JOIN does what you want:
SELECT . . . -- list out the columns you want
FROM inventory i INNER JOIN
cities c
ON i.city_id = c.city_id
WHERE i.is_enabled = 1
ORDER BY i.inventory_id DESC
LIMIT 10;
This query assumes that the inventory rows have a valid city_id. If some are NULL (an allowed, non-matching value), you can use LEFT JOIN instead.
Some other notes:
List out the columns you want explicitly. In particular, duplicate column names can be problematic.
Use table aliases, so the query is easier to write and to read.
Qualify all column names. I'm guessing that is_enabled comes from inventory. I should not have to guess.
Do not put single quotes around numeric constants. I am guessing that is_enabled is a number, not a string.
I'm trying to get this output with MySQL:
-Kate
-William
-dog
(3 results)
From those databases:
--------------- ----------------------
| users | | pet |
|-------------| |------|------|-------
| id | Name | | user|animal|number|
|-------------| |------|------|------|
| 1 |Kate | | 1 | cat | 0 |
| 2 |William| | 2 | dog | 1 |
--------------- ----------------------
Number needs to be != 0
and I need to be able to make the difference between a fetch where number = 0 and number != 0
SELECT
name, animal
FROM
users
INNER JOIN pet ON users.id = pet.user
WHERE
number != 0'
I can't get 'Kate' because never matching != 0.
I think I should use 2 different WHERE conditions in one request, but I don't know how...
First give your tables an alias because you have a ambigious column name id.
SELECT u.name, p.animal
FROM users AS u
INNER JOIN pet AS p
ON u.id = p.id
WHERE p.number != 0
But what you asking for is to get results from both tables without join, right? Like this
SELECT
name AS creatur,
'users' AS type
FROM users
UNION
SELECT
animal AS creatur,
'pet' AS type
FROM pet
WHERE number != 0
First. Use aliases for tables. Use, for example, 'u' for users table and 'p' for 'pet'. Mysql do not understand which field get from which table without aliases.
Second. Condition in WHERE section not related to JOIN. Use AND in ON section.
Third. Use LEFT JOIN instead of INNER JOIN and read articles about types of JOIN and differency between them.
Fourth. In such cases in users table usually adding field pet_id. Do not use single id field for both entities. This thing named ONE-TO-MANY relation. If you want use MANY-TO-MANY relation, you must add third table with two fields user_id and pet_id.
But this query may solve your question:
SELECT u.Name, p.animal
FROM users AS u
LEFT JOIN pet AS p ON u.id = p.user AND p.number != 0
I have two tables in a database:
entries (ID, distance, status[,...])
entriesmeta (ID, entry_ID, metakey, metavalue)
Until now, I select entries like this:
SELECT ID,
distance
FROM entries
WHERE status = '2' HAVING distance < 30
ORDER BY distance
LIMIT 20
Now, the second table contains data of this sort:
ID | entry_ID | metakey | metavalue
1 | 137 | service | 13
2 | 137 | service | 7
3 | 137 | service | 76
4 | 84 | service | 23
etc.
The entries in the first table are restaurants, the services in the second table are services they offer. What I have been trying for a while now is this: Create a HTML search form that lets users choose certain services via checkboxes. The MYSQL query then should select all entries that offer ALL those services. So far, the search form puts the selected services in an array (7,13,9,27).
My problem is finding the correct database query. It should match the metavalue-field with the checkbox-array and then select all entries from the first table, which offer all those services. I have been experimenting with "LEFT JOIN ON entries.ID = entriesmeta.entry_ID" and several WHERE clauses, but no success. I wonder if someone can help.
Thank you in advance - and sorry for my bad English.
SELECT e.ID
FROM entries e
INNER JOIN entriesmeta m
ON e.ID = m.entry_id
WHERE
m.metakey = 'service' AND
m.metavalue IN (7,13,9,27)
GROUP BY e.ID
HAVING COUNT(DISTINCT m.metavalue) = 4
SQLFiddle Demo
This query will display all ID that has metakey of service and a value(s) of 7, 13, 9, 27.
This would get you all entries which have a given entriesmeta service value - which is what I think you are asking.
SELECT entries.* from entriesmeta
INNER JOIN entries on entries.ID = entriesmeta.entry_ID
WHERE entriesmeta.metavalue = <myValue>
I have two tables, one table is called queuelist and the other is call info. In the queuelist table it just lists different IDs. I am trying to get the 'clientID' from that table and match it with the 'ID' in the other table that contains all of the info and display it back on the page. Here is how the tables look:
Table - queuelist
ID | clientID
-------------
1 | 589
2 | 254
3 | 486
Table - info
ID | Name | Phone
--------------------
256 | Bob | 5551231234
486 | Jack | 5551231234
589 | Jill | 5551231234
This is what they call joining tables, you should use a query like this:
SELECT i.ID, i.Name, i.Phone FROM `queuelist` AS q
LEFT JOIN `info` AS i ON (
q.clientID = i.ID
);
I'm using aliases for shorter notation in the above query (queuelist becomes q and info becomes i) and then set the join condition (the bit between the ON()) to be the clientID from the queuelist table should match the ID in the info table.
Also see http://dev.mysql.com/doc/refman/5.0/en/join.html for more details.
You need to use an inner join
select * from queuelist as ql inner join info as i on ql.clientID = i.ID
Though you might want to replace * with specific field names e.g
select ql.clientID, i.fieldname FROM....
Well, I see no difficulty in this using a JOIN.
SELECT * FROM queuelist JOIN info ON clientID = info.ID WHERE queuelist.ID = 2
"Where" would be another option.
SELECT Name, Phone FROM queuelist,info WHERE clientID = ID
Assuming you want only name and phone