was wondering if someone could help a newbie out with some sql?
Right so basically I want to get all the CustomerID's associated with a certain countrycode I can get that by doing a simple query on the customer table however I then need to find out how many forms the customer has submitted in the order table.
so in summary I need to get a list of customerID's from the Customer table and count how many time they show up in the Order table.
What's the easiest way to go about this?
P.S. please ignore any data type / relationship issues with the image above, it's just an example.
Thanks.
Join the tables, filter on country code and group the results:
SELECT CustomerID, COUNT(*)
FROM query_test.customer JOIN query_test.Order USING (CustomerID)
WHERE query_test.customer.countrycode = ?
GROUP BY CustomerID
You could use
SELECT
c.customerID,
count(o.form_id) AS form_count
FROM
customer c INNER JOIN order o
ON c.customerID = o.customerID
WHERE
c.countrycode = ??
GROUP BY
c.customerID
If you have customers that don't have any orders, then you will want a left outer join:
SELECT c.CustomerID, COUNT(o.CustomerID) as NumOrders, COUNT(distinct FormID) as NumForms
FROM query_test.customer c LEFT JOIN
query_test.Order o
on c.CustomerID = o.CustomerId
WHERE c.countrycode = ?
GROUP BY c.CustomerID;
Note this counts both the number of orders and the number of forms.
Related
I have 3 tables offers countries and transactions and what I'm trying to do is extract the offers from a specific country and devices, I already do this with this formula:
SELECT
*
FROM countries a
INNER JOIN offers b ON a.id = b.offer_id
WHERE a.country = "US"
AND b.device = 'all'
UNION
SELECT
*
FROM countries a
INNER JOIN offers b ON a.id = b.offer_id
WHERE a.country = "US"
AND b.device LIKE 'iphone%';
This code works but now I want to exclude the offers with the same ref between the tables users and transactions
the way this should work is:
The user from X country enter on Y device.
The user select an offer according to his country and device.
The offer is registered via post back to transactions.
The user enter to the main page and not longer see the offer he already finish.
Right now i'm capable of do the 3 first steps but not the fourth step. Any help about how do this?
Here is an example of the tables: SQL Fiddle
Thanks in advance
EDIT
if I put all this on words would be something like:
Select all from *offers* where the **offer_id** match with **ID** from *countries* with the **country** "US" and also from *offers* have the **device** "iPhone" now exclude from *transactions* the offers with the **user** = "xxxxx"
I hope this explain a little bit what I'm trying to do
Can't see how the query is user-specific , but to exclude offers refered to from transactions you can use NOT EXISTS
SELECT *
FROM countries a
INNER JOIN offers b ON a.id=b.offer_id
WHERE a.country="US" AND b.device = 'all'
AND NOT EXISTS (SELECT 1 FROM transactions t WHERE t.offer = b.offer_Id)
You could solve it with a LEFT OUTER JOIN to the transactions table.
I added t.id IS NULL to the WHERE-clause. So your result will just display offers which have no transaction.
SELECT *
FROM countries a
INNER JOIN offers b
ON a.id = b.offer_id
LEFT OUTER JOIN transactions t
ON t.id = b.offer_id
WHERE a.country = "US"
AND t.id IS NULL
Regarding your question it is still unclear for me how the tables users & countries are connected. This is an important detail, as the LEFT OUTER JOIN should just grab transactions from this specific user. So the condition transactions.user = user.ref should be added to the join too.
Will update the answer whenever you explain me this link
Imagine that there are two tables called: Customers, Orders.
In Customers we have rows:
id=1 name=Alex key=12
id=2 name=Bob key=13
and in the Orders we have:
id=1 device=phone status=ordered key=12
id=2 device=phone status=delivered key=12
id=3 device=memory status=ordered key=13
id=4 device=memory status=returned key=13
Now I want it to choose the last one for each one of them in the Customers from Orders. Like it should choose Alex's information and the last row that is inserted for him in the Orders table.
How can I make a query for this?
You can do this with aggregation and a join:
select o.*
from customers c left join
orders o
on c.key = o.key left join
(select o.key, max(id) as maxid
from orders o
group by o.key
) ok
on o.id = oo.id;
The aggregation gets the latest value.
Note that key is a reserved word in MySQL (see here). That makes it a lousy column name, so you should change it.
Sounds like you're looking for the group-wise (key) maximum (id) as explained at https://dev.mysql.com/doc/refman/5.6/en/example-maximum-column-group-row.html
I prefer (for no good reason) the LEFT JOIN variant over the uncorrelated sub-query.
Here is a way you can do it
select
c.*,
o.id,
o.device,
o.status
from customer c
join orders o on o.`key` = c.`key`
join (
select max(id) as id,`key` from orders
group by `key`
)o1 on o1.id=o.id
http://www.sqlfiddle.com/#!9/96885/2
I have a query
SELECT jss_products.* from jss_products_tree,jss_products
WHERE stock!=0 AND
jss_products.productID = jss_products_tree.productID
and sectionID=1 order by price
Which returns me a big array with products. Now I need to join 3rd table jss_extrafields_values,
which has productID and content fields, and somehow order the array by the content from 3rd table. Also it might have more than one rows with different content but same product.ID.. any ideas on how to join all of them? I tried a lot of tutorials but none of them helped me.. thanks
Its easier to use join over from table1, table2 as its better to read. And you can just join the 3th table.
SELECT jss_products.* from jss_products_tree
INNER JOIN jss_products
ON jss_products.productID = jss_products_tree.productID
INNER JOIN jss_extrafields_values
on jss_extrafields_values.productId = jss_products.productID
WHERE stock!=0 AND
and sectionID=1
order by jss_extrafields_values.field
I have a database with three tables:
Products
MaterialsProducts
Materials
The relationship between the tables are like this:
Materials 1-* MaterialsProducts *-1 Products
Quite often I need to retrieve 200+ products and their related material data (from the Materials table).
Currently it is done like this:
SQL: select all relevant products
PHP: iterate through the selected products, calling the database to select material data for each product(generating a database call for each product!)
Is there a way to select all relevant products + their material data at the same time? And still have each product only take up one row in the result.
So the solution shouldn't be "SELECT * FROM products p, materialsproducts mp, materials m WHERE p.id = mp.productid AND m.id = mp.materialid WHERE x". (That SELECT would make each product take up more than one row in the result.)
you can use left join to get all data you need
documentation here
Your query have a mistake
"SELECT * FROM `products` p LEFT JOIN `materialsproducts` mp on p.`id` = mp.`productid` LEFT JOIN `materials` m ON m.`id` = mp.`materialid` WHERE $whateveryouneed"
remember to not limit your WHERE to only 1 ID otherwise you will need more queries.
UPDATED
as asked
products has a 1-* relationship with both materialsproducts and typesproducts. materialsproducts has a *-1 relationship with materials. typesproducts has a *-1 relationship with types.
So you can make a left join query as above in this way
SELECT * FROM `products` p
LEFT JOIN `materialsproducts` mp
ON p.`id` = mp.`productid`
LEFT JOIN `materials` m
ON mp.`mp_field_id_here` = m.`m_field_id_here` //here you need to change with actual field to compare
LEFT JOIN `typesproducts` tp
ON p.`id` = tp.`tp_field_id_here` //here you need to change with actual field to compare
LEFT JOIN `types` t
ON tp.`tp_field_id_here` = t.`t_field_id_here` //here you need to change with actual field to compare
then you can add a where statment to limit result to something that suits you
WHERE WHATEVER_YOU_NEED
UPDATED AGAIN
to limit result to only some filed just change * to something specific as
"SELECT p.`Product_Name`, m.`Material_1`, m.`Material_2, m.`Material_3`, t.`Type_1`, t.`Type_2` FROM .....
NOTE I assume you retrieve material 1, material 2, material 3 from material table wich is why i used as prefix m. Either way i used as prefix t for type 1 and type 2 because i thought they are fileds of type table, otherwise you can change them according to your needs.
Try
SELECT p.*, mp.*,m.*
FROM products p
JOIN materials m ON p.id=m.prd_id
JOIN materialsproducts mp ON m.mp_id=mp.id;
It is not simple to have a query like this compress the materials data into a single row for each product - so I don't think that plan will work well for you.
What I would recommend instead is to use a normal JOIN query (much like the one you put in your question and rejected), then use PHP code to deal with the cases where a single product has multiple rows in the result set because it is linked to multiple materials.
You could use GROUP_CONCAT to combine materials related to the same product into a single list while grouping by products:
SELECT
p.ProductID,
p.ProductName,
GROUP_CONCAT(m.MaterialName) AS Materials
FROM Products p
INNER JOIN MaterialsProducts mp ON p.ProductID = mp.ProductID
INNER JOIN Materials m ON m.MaterialID = mp.MaterialID
GROUP BY
p.ProductID,
p.ProductName
;
I have two tables like these
Invoice (invoice_no, invoice_date, customer_id, ...),
Customers (customer_id, customer_name, ...)
Now what I want to do is list invoices ordered by customer name.
SELECT b.customer_name, a.*
FROM Invoice a, Customers b
WHERE a.customer_id=b.customer_id
ORDER BY b.customer_name
but problem with this sql is that if there are invoices without customer_id,
how can I list those invoices first and invoices with customer_id by customer_name asc.
use LEFT JOIN instead.
"kinda" weird. How come there are some invoices that without customer? To whom are you issuing it? Anyway, here's the query.
SELECT a.*, b.* // SELECT only the columns you want
FROM Invoice a
LEFT JOIN Customers b
ON a.customer_ID = b.customer_ID
To fully gain knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
SELECT
a.*,
b.customer_name
FROM Invoice a
LEFT JOIN Customers b ON a.customer_ID = b.customerID
Use joins instead of FROM tablea, tableb.
Because this will fetch cartisian product from both tables unless you restrict them with WHERE
Use this
SELECT * FROM Invoice,customer where Invoice.customer_id=customer.customer_id ORDER BY IF(Invoice.customer_id is NULL , Invoice.customer_id, ~Invoice.customer_id) ASC