I have a table with attributes to a product:
product_attributes
+------------+--------------+-------------+------+
| product_id | attribute_id | language_id | text |
+------------+--------------+-------------+------+
| 1 | 2 | 2 | bla |
| 1 | 2 | 3 | blo |
| 1 | 3 | 2 | foo |
| 1 | 4 | 3 | bar |
+------------+--------------+-------------+------+
and I have another table called product with multiple product_ids that do not exist in the product_attributes table.
I would like to copy all data from product_attributes where product_id = 1 and insert them for ALL the ids in the product table.
This is what I had so far but it does not work.
INSERT INTO `product_attribute`(`product_id`, `attribute_id`, `language_id`, `text`) SELECT (SELECT 'product_id' FROM `product`), `attribute_id`, `language_id`, `text` FROM `product_attribute` WHERE `product_id` = '1';
It says the subquery returns more than 1 row (which it does, that's the point), I just don't know how to solve this with 2 subsets.
use cross join :
[1] solution :
INSERT INTO `product_attributes`(`product_id`, `attribute_id`,`language_id`, `text`)
select product_id,v.attribute_id,v.language_id,v.text
from product
cross join (SELECT attribute_id, language_id, text
FROM product_attributes
WHERE product_id = '1') v ;
[2] solution :
INSERT INTO `product_attributes`(`product_id`, `attribute_id`,`language_id`, `text`)
select b.product_id,`attribute_id`, `language_id`, `text`
from product_attributes a
CROSS join product b
use above sql query it is perfect and it has no error.
your sql :
INSERT INTO `product_attribute`(`product_id`, `attribute_id`, `language_id`, `text`)
SELECT (SELECT 'product_id' FROM product), attribute_id, language_id, text
FROM product_attribute
WHERE product_id = '1';
Here,in your sql (SELECT 'product_id' FROM product) returns
more than one value it is not possible in co-related sql.
when inner query behaves as a field then at a time it has only one value .
(SELECT 'product_id' FROM `product`)
In this query should be return more than one row.
I think this query should be not required.
Related
I have orders table where i show information about order number, products, and customer.
I need to show list of product names and their qty in column products separated or in new row like below in table:
Expected result
id | order_number | customer | address | total | products
------------------------------------------------------------------------------------
1 | OR00123 | Tom Helks | Test 221 | 1233,2 | 1x iphone
| 2x samsung
| 3x someproduct
Order table
id | order_number | customer_id | total | status_id
------------------------------------------------------------------------------------
1 | OR00123 | 1 | 1233,2 | 1
OrderProducts table
id | order_id | product_id | qty |
------------------------------------------------------
1 | 1 | 5 | 1 |
2 | 1 | 2 | 2 |
3 | 1 | 6 | 3 |
Product table
id | name | price
----------------------------------------
5 | iphone | 1231
2 | samsung | 2322
6 | someproduct | 432
What i try.
I get above expected result but only dont do subquery for listing products and qty for order.
SELECT
order.number,
customer.name,
customer.adress,
SUM(order_products.qty * product.price) as total,
# subquery here
(
SELECT p.name FROM products p WHERE order_products.product_id = p.id
) as products
FROM.orders as order
INNER JOIN customer on customer.customer_id= customer.id
INNER JOIN order_products on order.id = order_products.order_id
ORDER BY dok.created_at;
My imagination stopped and I believe that the problem is in the sub-query, but I can't see it at the moment.
Thanks
You need to join all tables and GROUP BY the unique values.
The GROUP_CONCAT has to be used with then CONCAT of the wanted values
CREATE TABLE orders
(`id` int, `order_number` varchar(7), `customer_id` int, `total` varchar(6), `status_id` int)
;
INSERT INTO orders
(`id`, `order_number`, `customer_id`, `total`, `status_id`)
VALUES
(1, 'OR00123', 1, '1233,2', 1)
;
CREATE TABLE orders_product
(`id` int, `order_id` int, `product_id` int, `qty` int)
;
INSERT INTO orders_product
(`id`, `order_id`, `product_id`, `qty`)
VALUES
(1, 1, 5, 1),
(2, 1, 2, 2),
(3, 1, 6, 3)
;)
Records: 3 Duplicates: 0 Warnings: 0
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1
CREATE TABLE product
(`id` int, `name` varchar(11), `price` int)
;
INSERT INTO product
(`id`, `name`, `price`)
VALUES
(5, 'iphone', 1231),
(2, 'samsung', 2322),
(6, 'someproduct', 432)
;
Records: 3 Duplicates: 0 Warnings: 0
SELECT
order_number, `customer_id`, `total`,GROUP_CONCAT(CONCAT( op.`qty`,'x ',p.`name`) SEPARATOR ' ') products
FROM orders o
JOIN orders_product op ON o.`id` = op.`order_id`
JOIN product p ON op.`product_id` = p.`id`
GROUP BY order_number, `customer_id`, `total`
order_number
customer_id
total
products
OR00123
1
1233,2
1x iphone 2x samsung 3x someproduct
fiddle
We have a table in which we have the product ID, the price, and the shop ID.
the key is on the couple (product-id/shop-id) so we can have twice the same product in the same shop.
table item_price
Product_ID | Shop_ID | Price
1 | 2 | 25.99
1 | 3 | 40.00
1 | 1 | 10.00
2 | 9 | 32.00
3 | 2 | 78.00
and a table Item_reference which contains the Product_name, product_id and the retail_price_eur
Item reference
product_title | product_id | retail_price_eur
product_1 | 1 | 19.99
product_2 | 2 | 29.99
product_3 | 3 | 79.99
My goal is to select the product 1, for which the discount is the bigger with the following request:
SELECT DISTINCT t1.product_id
, t2.retail_price_eur
, t2.product_title
, t1.price, CEIL ((t1.price-t2.retail_price_eur)/t2.retail_price_eur*100) AS product_discount
FROM item_price AS t1
JOIN item_reference AS t2
ON t1.product_id = t2.product_id
WHERE t1.product_id = 1
AND NOT retail_price_eur = 0
ORDER
BY product_discount DESC
so, I have a couple of issue:
Issue 1)
Even tho I put DISTINCT, I have duplicates of the same product_id...
(but if i only ask for "SELECT DISTINCT t1.product_id" without any other field from t1 i do not have duplicates). So I have an issue I do not understand..
Issue 2)
I do not know how to integrate the code allowing to select the smaller Minimum Discount.
I would assume something along the line of
"WHERE NOT retail_price_eur = 0 AND MIN(product_discount)"...
but this is not the correct answer and i do not know how to put it in.
PS: I use "min()" on product discount, as in some cases, the % of variation might be positive if the shop price is superior to the retail price.
here are the command to create the example:
CREATE TABLE evilbrick.item_price ( product_id INT NOT NULL , shop_id INT NOT NULL , price FLOAT NOT NULL ) ENGINE = MyISAM;"
CREATE TABLE evilbrick.item_reference ( product_title VARCHAR (10) NOT NULL , product_id INT NOT NULL , retail_price_eur FLOAT NOT NULL ) ENGINE = MyISAM;
INSERT INTO item_price (product_id, shop_id, price) VALUES (1, 2, 25.99)
INSERT INTO item_price (product_id, shop_id, price) VALUES (1, 3, 40)
INSERT INTO item_price (product_id, shop_id, price) VALUES (1, 1, 10)
INSERT INTO item_reference (product_title, product_id, retail_price_eur) VALUES ('product_1', 1, 19.99)
I have an existing populated MySQL table with three columns: product_id, category_id and catalog_id
Each catalog has multiple categories in it and each category has multiple products in it. Categories belonging to the same catalog should have exactly the same products in them, but unfortunately they don't in certain cases.
I need to identify the missing products in each category. Missing means that a product exists in at least one other category that belongs to the same catalog but doesn't exist in that particular category.
So the result I need to get out of this is a list of product_id/category_id pairs that are missing and need to be added.
How do I accomplish this in MySQL?
I tried creating a table populated by the distinct product_id and catalog_id pairs to get all the products for each catalog and then join that with the main table, but I am not sure what type of join to perform.
Any MySQL experts willing to help?
Update:
Based on a request, here is the create table SQL (this is a simplified version of the actual scenario):
create table product (
product_id bigint not null,
category_id bigint not null,
catalog_id bigint not null
);
Update 2:
Clarification: Every category that belongs to the same catalog must have the same exact products in it as all the other categories that belong to the same catalog. If a product is in one category and not in another category that belongs to the same catalog, then it is missing and needs to be identified as a product_id/category_id pair.
Update 3:
Per another request, here is sample data:
insert into product (product_id, category_id, catalog_id) values (1, 1, 1);
insert into product (product_id, category_id, catalog_id) values (2, 1, 1);
insert into product (product_id, category_id, catalog_id) values (3, 1, 1);
insert into product (product_id, category_id, catalog_id) values (1, 2, 1);
insert into product (product_id, category_id, catalog_id) values (3, 2, 1);
In this case the pair of product_id 2 and category_id 2 would be identified as part of the result. This is because categories 1 and 2 belong to the same catalog (1) and category 2 has a missing product, namely product_id 2.
You can do it using the following query:
SELECT s1.product_id, s1.category_id
FROM (
SELECT t1.product_id, t2.category_id, t1.catalog_id
FROM (
SELECT DISTINCT product_id, catalog_id
FROM product) AS t1
CROSS JOIN (
SELECT DISTINCT category_id, catalog_id
FROM product) AS t2
WHERE t1.catalog_id = t2.catalog_id ) AS s1
LEFT JOIN product AS s2
ON s1.catalog_id = s2.catalog_id AND
s1.category_id = s2.category_id AND
s1.product_id = s2.product_id
WHERE s2.product_id IS NULL
Demo here
Explanation:
This query:
SELECT DISTINCT product_id, catalog_id
FROM product
gives you a list of all distinct products per catalog:
product_id catalog_id
-----------------------
1 1
2 1
3 1
If you perform a CROSS JOIN of the above to all distinct categories per catalog:
SELECT t1.product_id, t2.category_id, t2.catalog_id
FROM (
SELECT DISTINCT product_id, catalog_id
FROM product) AS t1
CROSS JOIN (
SELECT DISTINCT category_id, catalog_id
FROM product) AS t2
WHERE t1.catalog_id = t2.catalog_id
you get:
product_id category_id catalog_id
----------------------------------
1 1 1
1 2 1
2 1 1
2 2 1
3 1 1
3 2 1
The above is a comprehensive set containing the full list of product_id per category_id per catalog_id.
All you have to do now is to find the missing product_id, category_id pairs from your table. You can do that with a use of a LEFT JOIN as in the initial query.
You can also do by this in optimize way-
Hitesh> select * from product; +------------+-------------+------------+
| product_id | category_id | catalog_id |
+------------+-------------+------------+
| 1 | 1 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
| 1 | 2 | 1 |
| 3 | 2 | 1 |
| 4 | 2 | 1 |
| 5 | 2 | 1 |
| 1 | 2 | 2 |
| 2 | 1 | 2 |
+------------+-------------+------------+
9 rows in set (0.00 sec)
Hitesh>
SELECT product_id, category_id, catalog_id
FROM
(SELECT DISTINCT p1.product_id, p2.category_id, p1.catalog_id
FROM product p1 JOIN product p2 ON p1.catalog_id=p2.catalog_id) tmp
WHERE NOT EXISTS (SELECT 1 FROM product
WHERE category_id = tmp.category_id AND
product_id=tmp.product_id AND
catalog_id=tmp.catalog_id);
+------------+-------------+------------+
| product_id | category_id | catalog_id |
+------------+-------------+------------+
| 4 | 1 | 1 |
| 5 | 1 | 1 |
| 2 | 2 | 1 |
| 2 | 2 | 2 |
| 1 | 1 | 2 |
+------------+-------------+------------+
5 rows in set (0.00 sec)
Background:
I'm running a query which gets the total widgets, sprockets, and gizmos ordered by the customer during the last month
I also have a Total Orders column which runs a subquery counting every order in that month
The reason I do Total Orders in a subquery, instead of just adding the three columns, is because I also have a further two Total Orders columns for the two previous months
I have an orders table that stores financial records, and separate tables for actual product details for widgets, sprockets, and gizmos
The problem:
Occasionally, a widget might be 'half-deleted' (don't ask!) - where it has an orders record, but not a corresponding widgets record
I do not want to count this in the Total Widgets column - which is easy enough, as I just do a JOIN
However, I also do not want to count this in the Total Orders column...
My current query looks like this for Total Widgets:
SELECT
COUNT(orders.id)
FROM orders
JOIN widgets ON widgets.id = orders.item_id
WHERE orders.product_id = 1 -- Product ID 1 is a Widget
AND orders.date BETWEEN "2014-09-01 00:00:00" AND "2014-09-30 23:59:59"
So this will get all 'accurate' widgets, with an intact widget table record.
Here is my current query for Total Orders:
SELECT
COUNT(orders.id) AS count
FROM orders
JOIN widgets ON widgets.id = orders.item_id AND orders.product_id = 1
WHERE orders.date BETWEEN "2014-09-01 00:00:00" AND "2014-09-30 23:59:59"
So my thinking is that the above query should only JOIN when the order has a product_id of 1. However, it JOINs in every case. Which means if we've ordered 10 widgets (2 of which have been half-deleted), 5 sprockets, and 5 gizmos, rather than showing 18 orders, it only shows 8. Changing to a LEFT JOIN shows 20, which is still wrong, it should be 18.
Hopefully the above makes sense - thanks in advance.
okay so... the straight join doesn't work because you filter for orders.product_id = 1 and so it won't count sprockets or gizmos. just widgets. and if you have 2 half deleted, but 10 on record... 8 is the correct answer. the left outer join lets it join on rows where product_id <> 1, too, so all rows from orders (which contains order records on widgets, sprockets, gizmos - half deleted or not). but this also allows those 2 half deleted rows.
why don't you just do a straight join? if you want the answer 18, just join orders and products and count it. do not filter for widgets only. do not do a left outer if you don't want half deleted.
create table product (
product_id int,
product_name varchar(20)
);
insert into product values (1,'widget');
insert into product values (2,'sprocket');
insert into product values (3,'gizmo');
create table `order` (
order_id int,
widget_id int
);
insert into `order` values (1,1);
insert into `order` values (1,2);
insert into `order` values (1,3);
insert into `order` values (1,4); -- half deleted
insert into `order` values (2,1);
insert into `order` values (2,2);
insert into `order` values (3,3);
insert into `order` values (3,4); -- half deleted
insert into `order` values (4,4); -- half deleted
select o.order_id, count(*)
from `order` as o
join product as p
on o.widget_id=p.product_id
group by o.order_id
+----------+----------+
| order_id | count(*) |
+----------+----------+
| 1 | 3 |
| 2 | 2 |
| 3 | 1 |
+----------+----------+
3 rows in set (0.00 sec)
mysql> select o.order_id,
-> p.product_name,
-> (case when p.product_id is null
-> then 'half_deleted' else '' end) as half_deleted
-> from `order` as o
-> left outer join product as p
-> on o.widget_id=p.product_id
-> order by order_id ;
+----------+--------------+--------------+
| order_id | product_name | half_deleted |
+----------+--------------+--------------+
| 1 | gizmo | |
| 1 | NULL | half_deleted |
| 1 | widget | |
| 1 | sprocket | |
| 2 | widget | |
| 2 | sprocket | |
| 3 | gizmo | |
| 3 | NULL | half_deleted |
| 4 | NULL | half_deleted |
+----------+--------------+--------------+
I have two mysql tables: table_1 and table_2.
table_1:
| c_id | name | email |
| 1 | tom | t#t.com |
table_2:
| a_id | c_id | address | street |
| 1 | 1 | 67 | home |
| 2 | 1 | 68 | main |
How to create mysql query that will select table_1.name, table_1.email, table_2.address and table_2.street returning only one record like:
| name | email | address | street |
| tom | t#t.com | 67 | home |
Thanks for any suggestion.
Regards, T
Try this:
SELECT table_1.name, table_1.email, table_2.address, table_2.street
FROM table_1
JOIN table_2
ON table_1.c_id = table_2.c_id
GROUP BY table_1.c_id
SQLfiddle demo
The GROUP BY will determine which column you want to use to group the results by. B.T.W. if you like the change the column head you can add AS followed by the column head name (table_1.name AS "First name").
Table structure and sample data:
CREATE TABLE table_1
(`c_id` int, `name` varchar(3), `email` varchar(7))
;
INSERT INTO table_1
(`c_id`, `name`, `email`)
VALUES
(1, 'tom', 't#t.com')
;
CREATE TABLE table_2
(`a_id` int, `c_id` int, `address` int, `street` varchar(4))
;
INSERT INTO table_2
(`a_id`, `c_id`, `address`, `street`)
VALUES
(1, 1, 67, 'home'),
(2, 1, 68, 'main')
;
If you like to limit the sql query to a certain person say tom WHERE table_1.name LIKE 'Tom'. Like so:
SELECT table_1.name, table_1.email, table_2.address, table_2.street
FROM table_1
JOIN table_2
ON table_1.c_id = table_2.c_id
WHERE table_1.name LIKE 'Tom'
GROUP BY table_1.c_id;
You can also use = but with LIKE you can use wildcards like T%
you should use the SQL statement LEFT JOIN, for example
SELECT name, email, address, street
FROM table1
LEFT JOIN table2
ON table1.c_id=table2.c_id;
with the possible option WHERE name = 'tom'
select table_1.name as name, table_1.email as email, table_2.address as address, table_2.street as street
from table_1
left join table_2 on table_1.c_id = table_2.c_id