Let's say that I have the following tables in my MySQL database:
TABLE Products
| id | some_column1 | some_column2 |
TABLE ProductProperties
| id | product_id | name |
Oversimplified, but sufficient. Now I want to get all products with properties. I do:
SELECT * FROM `Products` JOIN `ProductProperties` ON Products.id = ProductProperties.product_id
What do I get?
| id | some_column1 | some_column2 | id | product_id | name |
It's not cool, and I want to make it cool in one of the two ways:
1) To get the array of objects like in Product table, but extended by one more member, which would be the array of properties which matched JOIN. I've sort of figured out already that it's impossible?
2) To get the array like this (I'd still have to iterate over it in PHP to join all properties in one product into one object):
| product_id | some_column1 | some_column2 | property_id | product_id | name |
So I'd like to rename the column ProductProperties.id into ProductProperties.property_id. If I could remove ProductProperties.product_id from the output too, that would be ideal, but for now, I only want the way to rename one column in the output. Or to prefix it by table name. Or something like that.
Doable?
You should explicitly name the columns and not use *. Then, don't return redundant columns:
SELECT p.id as productid, p.some_column1, p.some_column2,
pp.id as ProductPropertiesId, pp.name
FROM `Products` p JOIN `ProductProperties` pp
ON p.id = pp.product_id
Also, table aliases make such a query more readable.
SELECT Products.id product_id,
Products.some_column1,
Products.some_column2,
ProductProperties.id property_id,
ProductProperties.name
FROM `Products`
JOIN `ProductProperties`
ON Products.id = ProductProperties.product_id
Related
I am attempting to JOIN onto two different columns in the first table below from columns in the second and third tables.
I wish to JOIN users.id to job_listings.id to return users.username, and to also JOIN and delimit job_listings.categories to job_categories.id to return job_categories.description via FIND_IN_SET
job_listings
id | employer_id | categories
1 | 1 | 1,2
2 | 1 | 2
users
id | username | type
1 | foo | employer
2 | wat | employer
job_categories
id | description
1 | fun
2 | hak
I desire output that is of the following format:
output
username | type | category | description
foo | employer | 1 | fun
foo | employer | 2 | hak
foo | employer | 2 | hak
I have tried using various permutations of the following code:
SELECT users.username, users.type, job_listings.categories FROM users
JOIN job_listings ON users.id
JOIN job_listings AS category ON FIND_IN_SET(category.categories, job_categories.id)
ORDER BY users.username, category.categories
I know from other answers that I need to use an alias in order to use multiple JOIN operations with the same table, but despite adapting other answers I keep receiving errors related to declaring an alias, or returning output that has a column with the alias but no data returned in that column.
First, you should normalize your design. You should not store integer values in strings. You should not have foreign key references that you cannot declare as such. You should not store lists in strings. Is that enough reasons? You want a junction table for JobCategories with one row per job and one row per category.
Sometimes, we are stuck with other peoples lousy decisions and cannot readily change them. In that case, you want a query like:
SELECT u.username, u.type, jc.id, jc.category
FROM users u JOIN
job_listings jl
ON u.id = jl.employer_id and u.type = 'employer' join
job_categories jc
ON FIND_IN_SET(jc.id, j.categories) > 0
ORDER BY u.username, jc.category;
This query cannot take advantage of indexes for the category joins. That means that it will be slow. The proper data structure -- a junction table -- would fix this performance problem.
I have two tables in my database which I want to join some matching results from.
ps_product (column names): id_product | reference | price | wholesale_price
ps_stock (column names): id_product | quantity
I would like to combine these two tables to get:
Table: id_product | reference | quantity | price | wholesale_price
Both tables have matching id_product values and should be matched, so quantity fits the right reference and so forth. Saved to a csv file if possible.
Running mysql on Debian.
Thank you in advance!
You can do inner join as
select
p.id_product,
p.reference,
s.quantity,
p.price,
p.wholesale_price
from ps_product p
join ps_stock s on s.id_product = p.id_product
I'm trying to insert records from other tables into store_orders_items.
For example:
INSERT INTO store_orders_items( order_id, sel_item_id, sel_item_price)
SELECT order_id, sel_item_id, sel_item_price
FROM orders_ids
INNER JOIN store_orders ON store_orders.id = orders_ids.order_id
INNER JOIN store_shoppertrack ON store_items.id=store_shoppertrack.sel_item_id
Where session_id = '".$_COOKIE["PHPSESSID"]."';
Then I received the following message: Unknown column 'sel_item_price' in 'field list'. I tried to set sel_item_price As item_price to no avail.
Here are my tables:
store_orders_items:
id| order_id | sel_item_id |sel_item_price|
-------------------------------------------
| | | |
store_shoppertrack:
id| session_id | sel_item_id |date_added|
-------------------------------------------
| | | |
store_orders:
id| item_total| order_date|
---------------------------
| | |
store_items:
id| item_price| item_color|
---------------------------
| | |
orders_ids:
id| order_id | status|
----------------------
| | |
There is no table in jour join which has either a column named sel_item_price, nor a column item_price. The INSERT INTO has nothing to do with this, the SELECT on its own will fail just as well. I assume that you wanted to join with the store_items table as well, and select the item_price column from that table for insertion into the sel_item_price table of store_order_items. You could rewrite your SELECT like this:
SELECT order_id, store_shoppertrack.sel_item_id, store_items.item_price AS sel_item_price
FROM orders_ids
INNER JOIN store_orders ON store_orders.id = orders_ids.order_id
INNER JOIN store_items ON store_items.id = store_orders.sel_item_id
INNER JOIN store_shoppertrack ON store_items.id=store_shoppertrack.sel_item_id
Where session_id = 'foo';
The AS sel_item_price is optional, since you already specified the destination column in the INSERT INTO part. But it might help consistency, as the output of the SELECT will now hace volumns labeled the same as those of the target table. And it exhibits that you got the order of the AS wrong in your question, so you might learn something here.
I've created a SQL Fiddle for your schema and query.
The field sel_item_price is only in your store_orders_items table which is not part of your select query. This is the cause of the error you listed.
You need to also join against store_items, and include the column item_price from this table in your SELECT, not store_item_price which only exists in the table you are inserting into
According to this tables the only field sel_item_price is in the table store_orders_items which is the one you are going to insert the data. Thats why you got the error.
Your Query should be, you are using store_items alias but it is not in your join
INSERT INTO store_orders_items( order_id, sel_item_id, sel_item_price)
SELECT order_id, sel_item_id, sel_item_price
FROM orders_ids
INNER JOIN store_orders ON store_orders.id = orders_ids.order_id
INNER JOIN store_order_items
ON store_orders.id = store_order_items.order_id --missing
INNER JOIN store_shoppertrack
ON store_items.id=store_shoppertrack.sel_item_id
Where session_id = '".$_COOKIE["PHPSESSID"]."';
i have to check in my products i am selling (mostly gaming consoles and games)
i want to see which products has which categories and this is my query:
select * From products left join products_categories on (product_id=id) ;
+------+------+------------+-------------+----------
| id | name | product_id | category_id | and more
+------+------+------------+-------------+----------
| 4 | Xbox | 4 | 2 |
| 5 | PS3 | 5 | 2 |
| 7 | BAD | NULL | NULL |
etc...
+------+------+------------+-------------+---------
here i have a product (#7 - BAD) that i don'T want to see since i removed the category,
I don't want to see the product without categories?
The LEFT JOIN command is used to combines null matching rows which are
stored in related tables In order to join these tables, the join table
require a common field (commonly called foreign key) from the left
table. This type of join requires keywords ON or USING.
Example:
SELECT *
From products
LEFT JOIN products_categories ON (product_id=id)
WHERE product_id IS NOT NULL;
Or you can use the INNER JOIN:
The JOIN or INNER JOIN command is used to combines non-null matching
rows which are stored in related tables In order to join these tables,
the join table require a common field (commonly called foreign key)
from the left table. This type of join requires keywords ON or USING.
Example:
SELECT * From products INNER JOIN products_categories ON (product_id=id);
Now, I would recommend to add a flag for inactive or active product, this way you don't need to remove the categories for a product if it's inactive. This way, if you want to re-activate it, simply turn the flag back to 1 or whatever flag you use.
Example:
SELECT *
FROM products
INNER JOIN products_categories ON (product_id=id)
WHERE products.is_active = 1;
I have three tables, machines holding vending machines, products holding all possible products, and machines_products which is the intersection of the two, giving how many of each product line is stocked in a particular machine. If a product is not stocked in a machine, there is no corresponding row in the third table.
DESCRIBE machines_products;
+------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+-------+
| machine_id | int(10) unsigned | NO | PRI | 0 | |
| product_id | int(10) unsigned | NO | PRI | 0 | |
| quantity | int(10) unsigned | NO | | 0 | |
+------------+------------------+------+-----+---------+-------+
Each product has a category (think chocolate bars vs. drinks bottles) and a machine knows what category of products it can vend. I want a result table of all products for the category, with a quantity for a specific machine. I have got as far as this:
SELECT products.*, SUM(quantity) qty
FROM products
LEFT JOIN machines_products USING (product_id)
WHERE machine_id=m AND category_id=c
GROUP BY product_id;
The problem is that this filters out all rows where there is no quantity, whereas what I want is all rows from the left table, and NULL/0 in the qty column if there are no corresponding rows in the right-hand table.
BTW: this is not a homework question! I am 30 and sitting in my office :o)
SELECT p.*
, SUM(mp.quantity) AS qty
FROM products p
LEFT JOIN machine_products mp
ON mp.product_id = p.product_id
AND mp.machine_id = m --- this condition moved from WHERE to ON
WHERE p.category_id = c
GROUP BY p.product_id
Actually I figured out the answer a short while after posting. The trick is to avoid specifying either of the columns from the third table's primary key (i.e. machine_id and product_id) in the WHERE clause. By using an AND in the JOIN's ON condition, and specifying the machine ID there, I get the result I was looking for.
SELECT products.*, quantity
FROM products
LEFT JOIN machines_products
ON products.product_id=machines_products.product_id
AND machine_id=m
WHERE category_id=c
The COALESCE() function suggested by Brendan was not necessary in my case, since I check the value with PHP's empty() function, so NULL is fine.
As it turns out, there was never a need for GROUP BY, which I had been playing with when posting the question.
SUM returns NULL if a single value in the equation is NULL. COALESCE the value first and then SUM:
SELECT p.*, SUM(COALESCE(mp.quantity, 0)) AS qty
FROM products p
LEFT JOIN machine_products mp ON mp.product_id = p.id
WHERE mp.machine_id = m
AND p.category_id = c
GROUP BY p.id
I assumed you have a column in products called id. Rename if it's something different...
SELECT p.id, SUM(mp.quantity) AS qty
FROM products p
LEFT JOIN machines_products mp ON p.id=mp.product_id
WHERE mp.machine_id=m
AND p.category_id=c
GROUP BY p.id;