Select from 2 table SQL WHERE Clause by ID - mysql

I have 2 tables in MySQL, in both of these tables I have merchant_id, merchant, branch and some another fields, the name of one table is merchant and another table is product.
tbl_merchant :
id | merchant_id | merchant_name | branch | ...
------+---------------+--------------------+----------------+
1 | 1001 | McDonalds | branch 1 mcd | ...
2 | 2002 | KFC | branch 1 kfc | ...
tbl_product :
id | product_id | product_name | price | merchant_id
------+---------------+-----------------+---------+-------------
1 | 100101 | Chicken | 10 | 1001
2 | 100102 | Potato | 5 | 1001
3 | 100101 | Burger | 10 | 2002
4 | 100102 | Fish Fillet | 10 | 2002
I want to know how can to show merchant_name, branch from both tables using SQL WHERE Clause by product_id = 100101 and merchant_id = 1001 ?
Like this :
Result :
id | merchant | branch | product_name | price
------+-------------+----------------+---------------+-------
1 | McDonalds | branch 1 mcd | Chicken | 10
Thank You

First, I'll show you the query, then I'll explain each part line by line to help you understand:
SELECT
merchant_name, branch
FROM
tbl_merchant INNER JOIN tbl_product ON (tbl_product.merchant_id = tbl_merchant.merchant_id)
WHERE
product_id = 100101 AND merchant_id = 1001
Alright, so if we look at the first part following the select, it should be clear that the two columns that will be printed out are merchant_name and branch. Based on your output, you can print out any field from either table just by adding its name to the list. If the field has the same name in both tables, then you need to qualify it like this:
SELECT
tbl_merchant.id, tbl_product.id
FROM
tbl_merchant INNER JOIN tbl_product USING(merchant_id)
The tricky part of this query is the line that joins the two tables together. Essentially what you have as of now is two tables that are linked together by a merchant id, which makes sense because 1 merchant can have many products (i.e. a 1 to many relationship). I'm assuming that the merchant ID is unique. The join then pairs together all the rows that have the same merchant_id (which is unique in one of the tables and therefore guaranteed to be correct). More specially you can think of it as a qualified cross product where each tuple from tbl_product is joined with each tuple from tbl_merchant and then qualified based on the condition tbl_product.merchant_id = tbl_merchant.merchant_id.
The last part of the query (WHERE clause) simply eliminates rows based on the conditions provided.

The query for this is:
SELECT merchant_name, branch
FROM
tbl_merchant
INNER JOIN
tbl_product
ON (tbl_product.merchant_id = tbl_merchant.merchant_id)
WHERE
product_id = 100101 AND merchant_id = 1001

SELECT merchants.id, merchants.merchant_id, merchants.branch, products.product_name, products.price
FROM merchants
INNER JOIN products ON products.merchant_id = merchants.merchant_id
WHERE merchants.merchant_id = 1001 AND products.product_id = 100101
you can use JOIN to solve this type of query
there are some good article to learn more about JOIN with visula explanation::
1) http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/ "A Visual Explanation of SQL Joins"
2) http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins "Visual Representation of SQL Joins"

Try this:
select * from marchant join product on marchant.id=product.merchant_id where merchant_id = 1001
This statement will join both tables together where the primary key form merchant is equals the merchant_id in product.

Related

MySql Join and count number of records

I have two tables
tbl_groups:
id | name
----------------
1 | BSCS
2 | BSIT
3 | BBA
tbl_students:
id | name | group_id
-------------------------------
1 | Student Name | 1
2 | Student 2 | 1
3 | Student 3 | 2
I want to show groups details: group name and number of students in a particular group,
I am using this query but it shows groups that has students. it does not show group with 0 students.
select tb2.id, tb2.name, count(*) from tbl_students tb1 JOIN tbl_groups tb2 ON tb1.group_id = tb2.id
How do I show all groups, please give me some idea
EDIT:
if I use above query I get following result:
id | name | count(*)
-------------------------------
1 | Student Name | 2
2 | BSIT | 1
(it doest show 3rd group because there are 0 students, I want to show this groups also).
Just use a left join:
select tb2.id, tb2.name, count(tb1.id) as no_std
from tbl_groups tb2
LEFT JOIN tbl_students tb1 ON tb2.id = tb1.group_id
group by tb2.id, tb2.name
See it working live here: http://sqlfiddle.com/#!9/2282a3/5
I would just use a correlated subquery to get the count of students in each group, like so:
select
g.*,
(select count(*) from tbl_students s where s.group_id = g.id) no_students
from tbl_groups g
This does not filter out groups that have no students (it will give a count of 0 instead). And with an index on tbl_students(group_id), this should be as efficient as it gets (this index is already there if you set up a foreign key constraint on that column - as you should have).

Get data from one table and count matching records from another

I'm not sure if this is possible. I have one table members and a second table transactions.
I need to get the name of the member from the members table, but also count the number of transactions that member has made from another table. Is this even possible in a JOIN statement, or do I need to write two statements?
SELECT
m.first_name,
m.last_name,
COUNT(t.giver_id),
COUNT(t.getter_id)
FROM
members AS m
JOIN
transactions AS t
ON
m.id = t.giver_id
WHERE
m.id = $i
I should add that it's possible a member has not made any transactions and would therefore not appear in the transactions table.
When I run this code, it returns all NULL columns. When I add the EXPLAIN statement, MySql says "Impossible WHERE noticed after reading const table..."
Is this possible? If so, then what am I doing wrong? Thanks in advance.
EDIT:
Sample data structure and expected output:
members
id | first_name | last_name
_______________________________
1 | Bill | Smith
2 | Joe | Jones
transactions table
id | giver_id | getter_id | status
________________________________________
1 | 1 | 2 | complete
2 | 1 | 2 | complete
So running my query should return:
1 | Bill | Smith | 2 | 0
2 | Joe | Jones | 0 | 2
Simple LEFT JOIN should suffice:
SELECT
m.first_name,
m.last_name,
SUM(CASE WHEN m.id = t.giver_id THEN 1 END) AS giver_count,
SUM(CASE WHEN m.id = t.getter_id THEN 1 END) AS getter_count
FROM members AS m
LEFT JOIN transactions AS t ON m.id = t.giver_id OR m.id = t.getter_id
GROUP BY m.first_name, m.last_name
Do not forget adding GROUP BY when using aggregate functions. Just because MySQL allows the query to go through without it, it doesn't mean it is advised. MySQL will pick up random row values for unaggregated columns which can be problematic. Avoid this anti-pattern.

Many To Many join with additional where

I think I have a somewhat trivial question but I can't figure out how this works. I have the following Companies and Products tables with a simple Many-To-Many relationship.
How would I have to extend this query, so that the results just contains let's say all companies which have products with id 1 AND 2?
I tried adding wheres and havings wherever I could imagine but all i could get was all companies which have products with id x (without the additional and)
Companies Table
id | name
-----------------
1 | Company 1
2 | Company 2
3 | Company 3
Companies_Products Table
id | product_id | company_id
----------------------------
1 | 1 | 1
2 | 2 | 1
3 | 3 | 1
4 | 1 | 2
5 | 1 | 3
6 | 2 | 3
Products Table
id | name
-----------------
1 | Product A
2 | Product B
3 | Product C
Statement
SELECT companies.name,
companies.id AS company_id,
products.id AS product_id
FROM companies
LEFT JOIN company_products
ON companies.id = company_products.company_id
INNER JOIN products
ON company_products.product_id = products.id
If you want ALL companies with associated products 1 and 2, you can write this query:
SELECT c.name,
c.id AS company_id
FROM companies c
WHERE (SELECT COUNT(*)
FROM company_products cp
WHERE cp.company_id = c.id
AND cp.product_id in ('1', '2')
) = 2
Go to Sql Fiddle
If you want to know informations about associated product in the main query so you must use a join in addition of existing query.
Maybe you could using the following subquery in your query:
SELECT company_id, count(*) as no_companies
FROM Companies_Products
WHERE product_id IN (1, 2)
HAVING count(*) = 2
(In this case company an product must be coupled only once.) It returns all the company_ids with product 1 and 2.
There always some discussion about subquery's and performance, but I don't think you will notice.
You could make this function flexible by using a array.
pseudo code:
$parameter = array(1, 2);
...
WHERE product_id IN $parameter
HAVING count(*) = count($parameter)
Please say so if you need more help.

MySQL: select table records where related table has empty match

I have two tables with related information. "RoodCMS_prodQuants" and "RoodCMS_albums". These look as follows:
RoodCMS_prodQuants:
This table is a product quantity table. The combination idnr-prodID is unique. idnr refers the ID of an order in another table, prodID refers to idnr in "RoodCMS_albums"
-------------------------------------------------
idnr | prodID | kwantiteit
------------------------------------------------
2 | 2 | 2
3 | 1 | 1
4 | 1 | 2
4 | 2 | 2
5 | 3 | 1
RoodCMS_albums:
For administrative purposes, I only delete a record here if it is flagged as "to-be-deleted" (gepubliceerd = '-1'), and if there are no entries related to it anymore in the previous table (records from RoodCMS_prodQuants with the prodID as idnr in RoodCMS_albums). That's because I'd like to keep information like price, name until the last order containing this product is deleted.
-------------------------------------------------------------------
idnr | gepubliceerd | ... name, price, quantity-in-stock, etc...
-------------------------------------------------------------------
2 | 1 |
3 | 1 |
4 | -1 | <---- this one is flagged to be deleted
1 | 1 |
In this case, I want to select the idnr of each record that does not have any corresponding records under the same prodID. For the tables that I displayed here, that means idnr='4' is a candidate to be selected, as there is no record with prodID='4'.
I tried a couple of queries to collect the records that match my criteria.
SELECT r1.idnr
FROM RoodCMS_albums AS r1, RoodCMS_prodQuants AS r2
WHERE r1.gepubliceerd='-1' AND r1.idnr = r2.prodID
GROUP BY r1.idnr HAVING SUM(r1.kwantiteit) = 0
... and:
SELECT r1.idnr
FROM RoodCMS_albums AS r1, RoodCMS_prodQuants AS r2
WHERE r1.gepubliceerd='-1' AND r1.idnr = r2.prodID
GROUP BY r1.idnr HAVING COUNT(r2.prodID) = 0
Both return an empty set of rows, whereas I aim for selecting idnr='4' from RoodCMS_albums. Could someone help me with writing a query that does return the result I aim for?
Thanks in advance!
You want a left outer join (or not in or not exists). You should learn to use proper, explicit join syntax -- such habits would help you when you encounter an issue like this. The query is more like:
SELECT r1.idnr
FROM RoodCMS_albums r1 LEFT JOIN
RoodCMS_prodQuants r2
ON r1.idnr = r2.prodID
WHERE r1.gepubliceerd = '-1' and r2.ProdId is NULL;

How to combine MySQL number of rows of the joined table, including 0?

I have two tables: 'company' and 'order'. The first one contains company info and the second one holds all orders made with a company. (order.company = company.ID).
I am making a query on the first table, for example all companies in the city of New York. I would like to make a join with the order table, so that it immediately shows how many orders for a company was made. I could do this with a simple JOIN query, however, it does not include 0. For example, if a company has no orders yet, it will not show up at all, while it should be in the list with 0 orders.
Desired end result:
----------------------------------------
| ID | Name | ... | Orders |
----------------------------------------
| 105 | Company A | ... | 14 |
| 115 | Company B | ... | 5 |
| 120 | Company C | ... | 0 |
| 121 | Company D | ... | 0 |
----------------------------------------
Thanks in advance!
This is a left join with aggregation:
SELECT c.ID, c.Name, count(o.company) as total
FROM companies c left outer join
orders o
on c.id = o.company
WHERE c.city = 'New York'
GROUP BY c.ID;
In MySQL, it is best to avoid subqueries in the from clause -- where possible -- because the derived table is actually created.
The COUNT() expression is counting the number of matches by counting the number of non-null values in the id field used for the join.
Try this
SELECT com.id,com.name,od.orders FROM compnay AS com
LEFT JOIN orders AS od ON od.company = com.id;
SELECT companies.ID,companies.Name ,orders.total FROM
(SELECT ID,Name FROM company where county ='NEW YORK') companies
LEFT JOIN (SELECT company,COUNT(*) as total FROM order GROUP BY company) orders
ON orders.company = companies.ID