My database has two tables.
food_table:
+----+----------+---------------+
| ID | NAME | NutrientID |
+----+----------+---------------+
nutrient_table:
+------------+--------------+
| NutrientID | NutrientName |
+------------+--------------+
I want select all rows in food table, but get NutrientName instead of nutrientID.
If I do:
select * from food_table.
I will get NutrientID. Is it possible to get NutrientName in a single query?
SELECT f.*, n.NutrientName FROM food_table f
LEFT JOIN nutrient_table n
ON n.NutrientID = f.NutrientID
You need to make a join inner to tables filtering by field NutrientID , if you look this field as the same in two table and the join works fine.
Related
I have this app where I need to do a query and have two columns.This are my two columns and respective rows:
Name of table1: Machines(has a row called Machinesnames and a id_group as FK)
Name of table2: Groups (has a row called groupsnames and id_groups as PK)
The problem is that with the query you see below I am getting the following result
**GroupsNames** | **MachinesNames**
1 machine1
1 | machine2
1 | machine3
2 | machine4
I have done this but I think is wrong can you correct my query please?:
SELECT groups.name,Machines. Machinesnames,Groups.groupsnames FROM Machines INNER JOIN Groups ON Machines.id_group = Groups.id_group
This is the result I want to see
**GroupsNames** | **MachinesNames**
1 machine1,machine2,machine3
2 | machine4
You are looking for group_concat:
select g.name,
group_concat(m.Machinesnames)
from Machines m
inner join Groups g on m.id_group = g.id_group
group by g.name;
Your query is correct for a inner join, but from looking at your expected output you are wanting a aggregated list.
Try this answer for MySQL using GROUP_CONCAT()
Aggregate function in MySQL - list (like LISTAGG in Oracle)
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.
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
Look at this DB schema:
The users can order products. For any order I add a new record in the orders table and a new record in orders-products N:M table for any single product ordered by the user (and fill pieces field). But, when a user creating an order, I need to show the list of all products and fill the pieces field with the quantity ordered for any product.
Usually, to do it, I use two queries.
The first query get all products in the products table:
SELECT * FROM products;
The second query gets the products ordered in the orders-products table filtering them by orders-idorder FK:
SELECT orders_idorder AS idorder, products_idproduct AS idproduct, pieces FROM orders_products WHERE orders_idorder=1;
Then I merge the results in a single array and use it to display the complete list of products with the pieces ordered for each one. The final result is something like this:
+---------+-----------+--------------+-------+--------+
| idorder | idproduct | description | price | pieces |
+---------+-----------+--------------+-------+--------+
| 1 | 1 | Product 1 | 10.20 | 2 |
| 1 | 2 | Product 22 | 11.00 | NULL |
| 1 | 3 | Product 333 | 19.22 | NULL |
| 1 | 4 | Product 4444 | 9.20 | NULL |
+---------+-----------+--------------+-------+--------+
Note: In the above example there are 4 records in the products table and just 1 record in the orders-products table (it has idorder=1, idproduct=1 and pieces=2).
-> Here you can find the SQL Dump to test the queries.
Merging arrays built from 2 queries is the best way?
I can do it with a single query?
What do you think about the performance?
Generally letting the databse optimize the merge will be better than what you can do in code. The db is usually better at sorting too.
How you structure the query depends on your desired result set. If you want all products regardless of whether they appear in the orders table then you'd use an OUTER JOIN otherwise an INNER JOIN would filter out products that have never been ordered.
If you give us your desired results for some sample data we might be able to help you with the query, but give it a shot yourself first.
set #searchOrderId = 1;
select ifnull(op.orders_idorder, #searchOrderId) AS idOrder,
p.idproduct,
p.description,
p.price,
op.pieces
from products p
left join orders_products op on op.products_idproduct = p.idproduct
where ifnull(op.orders_idorder, #searchOrderId) = #searchOrderId ;
SQL Fiddle I was playing with to test it.
Sure you can get the information using a single query by JOINing the tables together. Is it what you're having troubles with?
I think that in general, executing a single query to retrieve the results will perform better than executing two queries and merging the results. It is impossible to say what the ideal plan for execution is, given the information provided. Table sizes, architecture, etc will play a role.
For retrieving all of the products from a single order, try:
select
o.idorder,
p.idproduct,
p.description,
p.price,
op.pieces
from
orders o
inner join orders_products op
on o.idorder = op.orders_idorder
inner join products p
on op.products_idproduct = p.idproduct
where
o.idorder = 1
I see, you wanted a LEFT JOIN from Products table into Orders_Products. This will give you result you're looking for.
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"]."';