How to add columns to another table based on one column? - mysql

I have my shop database and I want to join two tables together.
id_order | reference | id_shop_group | id_shop | id_carrier | id_lang | id_customer | id_cart
This the header row of my orders table and below is the header of customers table.
id_customer | id_shop_group | id_shop | id_gender | firstname | lastname
What I want to do is to join them based on id_customer column. More specifically I want to add all columns of customers except the ones that are already there to orders table based onid_customer. After joining the tables should look like this:
id_order|reference|id_shop_group|id_shop|id_carrier|id_lang|id_customer|id_cart|id_gender|firstname|lastname
When searching for a solution I found INNER JOIN keyword, but I'm not sure how to use it the way I want.

We don't "Add columns to a table". We, instead, submit SQL to the database that returns the result set that we want. In your case we want to Join the two tables and we can do that using an INNER JOIN on your id_customer field that is common between the two tables. We can turn that into it's own table if you want to hold, permanently, those results. It would look something like
SELECT
orders.id_order,
orders.reference,
orders.id_shop_group,
orders.id_shop,
orders.id_carrier,
orders.id_lang,
orders.id_customer,
orders.id_cart,
customer.id_gender,
customer.firstname,
customer.lastname
FROM orders INNER JOIN customer on orders.id_customer = customer.id_customer;
You can tweak the list of fields to be returned from the joining of these tables to suit your needs.

The fact that id_shop and id_shop_group are in both tables suggests they are part of a composite key. You may need to join using all three shared columns to guarantee unique rows. Otherwise you may retrieve duplicate order rows where the customer belongs to more than one shop.
e.g.
SELECT
...
FROM orders INNER JOIN customer on orders.id_customer = customer.id_customer
and orders.id_shop_group = customer.id_shop_group
and orders.id_shop = customer.id_shop

Related

Mysql subquery in where clause that returns comma separated value

I'm not really good at subqueries, here's the sample tables that I have.
table customers
=====================
id | name | order_ids
1 | John | 1,2
table orders
=====================
id | name
1 | apple
2 | orange
I'm trying to get the order names using this query, but I'm only getting one result. I'm not sure if this is possible.
select o.name
from orders o
where o.id IN(
select c.order_ids
from customers c
where c.id=1
)
Your primary effort should go into fixing your design. You should not be storing several integer values in a string column. If each order belongs to a single customer, then the customer id should be stored in the orders table. If an order may belong to multiple customers at once, then you need a bridge table, with one row per customer/order tuple.
That said: for you current design, you can use find_in_set():
select o.*
from orders o
inner join customers c on find_in_set(o.id, c.order_ids)
where c.id = 1

Improve this query to fetch data from different tables

This is my scenario. I have a table of events with a field type, with values 1 = food, 2 = recipe. Simplifying, my events table have this structure:
id | entity_id | user_id | type | timestamp | field1 | ... field n
Field "entity_id" refers to a unique autoincremental value from "Entities" table. Food and recipe table structure is very similar, with entity_id and user_id fields.
What I want is to get all the common data from the table events of last 10 registers, and fetch some needed fields of corresponding table based on type value of table events. By now I have achieved some quite similar, but not exactly what I want, with this query:
SELECT a.*, b.name, b.field1, b.field2, c.name, c.field1, c.field2
FROM events a
LEFT JOIN foods b ON b.entity_id = a.entity_id
LEFT JOIN recipes c ON c.entity_id = a.entity_id
ORDER BY timestamp DESC LIMIT 10
This allways returns all fields for all tables, with NULL values when the field is not of the type of this specific register.
So I want to get all fields of events table, and name, field1, field2 of the corresponding table.
EDIT:
Here is the sqlfiddle sqlfiddle.com/#!2/18d45/9 I'd like the query returned different field values based on the table. In the example table recipes has description field while foods not. Is it possible?
Please helpe me with this!
You might use a COALESCE to get the first not NULL column:
SELECT a.*,
COALESCE(b.name, c.name),
COALESCE(b.field1, c.field1),
COALESCE(b.field2, c.field2)
FROM events a
...

SQL join or merge results?

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.

MySQL create view joining two tables

How can I create a view that merges different columns with a different table? I have three tables for example: users, items and gifts (in this example it's a system that a user can give a gift to another user)
users table has information about users, items table has information about items and gifts table shows which user sent what gift to which user.
What I want is to create a view like following:
user_from | user_to | gift_name | gift_price
sally | john | Teddy Bear | 10
You must join the three tables first. Example
CREATE VIEW GiftsList
AS
SELECT b.name user_from,
c.name user_to,
d.name gift_name,
d.price gift_price
FROM gift a
INNER JOIN users b
ON a.user_from = b.id
INNER JOIN users c
ON a.user_from = c.id
INNER JOIN items d
ON a.item = d.id
You can create a view with two tables like:
CREATE VIEW giftList AS
SELECT users.user_from,users.user_to,gifts.gift_name,gifts.gift_price FROM users,gifts
WHERE users.user_id = gifts.user_id;
The where clause is to make sure the output does not repeat.
I believe were looking for data blending. So basically having google data studio do a JOIN statement on ids from 2 data sets

Change database structure: need an SQL query

I have two tables:
connections
id | publisherId | authorId
and
books
id | connectionId | title
I want to merge these tables to get only one table:
books
id| publisherId | authorId | title
How can I do this with only one SQL query?
CREATE TABLE newtable
SELECT b.id, c.publisherId, c.authorID, b.title
FROM books b
INNER JOIN connections c
on c.id = b.connectionId
Untested, but this should do it. I assume you want the ID from the books table, otherwise you need c.id instead of b.id.
Then you can drop the old tables and rename this to whatever you want.
CREATE TABLE connections_books
SELECT books.id as id,
connections.publisherId as publisherId,
connections.authorId as authorId,
books.title as title
FROM books join connections on books.connectionId = connections.id;
Test the query first using just the select part:
SELECT books.id as id,
connections.publisherId as publisherId,
connections.authorId as authorId,
books.title as title
FROM books join connections on books.connectionId = connections.id;
Once this gives you what you want, go ahead and create the table.
It's important to make sure the column names in the new table are correct. Use the select statement testing to ensure your column names are what you want. If you want to change the column names, change the as ... names for each column selected.