I have a good idea of the pseudo-logic of what I want to do - just struggling to think of the syntax to put it into practice.
I’ve got three tables:
product_images
product
product_import
At a high level - I want to insert a row into the product_images table with just two values (image_url, product_id) - the image url can be found in the product_import table along with an product_id. This product_id is the old ID of the product (migrating from another system) - this is recorded as old_id in the product table.
Therefore the retrieval of the image_url works conditionally on the basis that: the product_id in the product_import table has a match with the old_id value in the product table. If it does match - then insert the value of the matching image_url from the product_import table and the new product_id that matches from the product table (if the old_id is found)
My guess at the SQL statement is something along the lines of:
INSERT INTO product_image(image_url, product_id)
SELECT product_import.image_url, product.id WHERE product.old_id = product_import.id;
When you want to write an INSERT INTO ... SELECT ... statement, the first rule is to start by designing the SELECT ... part.
In your case, the select query is syntactically invalid because it is missing a FROM statement.
So a valid select would be something like:
SELECT product_import.image_url, product.id
FROM product_import
INNER JOIN product ON product.old_id = product_import.id;
You may have to tweak it a bit based on your needs but it is the minimum query to start working. And of course you add the INSERT part only when you are satisfied with your SELECT query.
This was what I needed in the end..
INSERT INTO product_images(image_url, product_id, account_id, is_thumbnail, created_at, modified_at)
SELECT `value`, id, account_id, "1", now(), now()
FROM product_import
JOIN product ON product_import.entity_id = product.old_id
WHERE product.account_id=1;
Related
I know guys, this might be a silly question, but I have not found any solution till now, so I am asking this question with all the inputs and outputs that I have done. Could anyone provide me the solution.
What I want to do is: the parcelno can have one or more invoicenumbers, I want to find how many invoice numbers does an parcel has and give it a rank. The ranking part is important because my further work is depending on this column.
I have one table named TableA. It has three columns Invoicenumber which is the unique id, ParcelNo which can be duplicate and Ranking which I want to update.
CREATE TABLE TableA
(
Invoicenumber varchar(5),
ParcelNo varchar(5),
Ranking bit,
IDate Datetime
)
INSERT INTO TableA (Invoicenumber, ParcelNo)
VALUES ('INV01', 'P0001'), ('INV02', 'P0001'),
('INV03', 'P0002'), ('INV04', 'P0002'),
('INV05', 'P0003'), ('INV06', 'P0003')
When I run the following query the output is as desired.
;WITH CTE AS
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY PARCELNO ORDER BY INVOICENUMBER) AS RWNO
FROM
TableA
)
SELECT
T.*, C.RWNO
FROM CTE C
JOIN TableA T ON T.Invoicenumber = C.Invoicenumber
The output is below:
So, I tried to update the Ranking column in Table A.
I run this query to do so:
;WITH CTE AS
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY PARCELNO ORDER BY INVOICENUMBER) AS RWNO
FROM
TableA
)
UPDATE T
SET Ranking = C.RWNO
FROM CTE C
JOIN TableA T ON T.Invoicenumber = C.Invoicenumber
But the output is wrong. The column is not updated as expected.
Below is the output of the updated column:
Why is the Ranking column is updated incorrectly?
I want to update the column to prepare some data. This table is sample for the explanation.
I am elaborating my issue below:-
Below in the image are two tables:-
Table A and Table B has IDate column.
I want to update the IDate column in A from B. But the dates should be unique. First date should not be repeated. These date are associated with Invoicenumbers.
I think what you really want is a calculated column (called a calculated field or generated field). I'm guessing that your parcel number should point to another table that stores information about the parcels. If that's the case, then go with:
-- First approach
CREATE TABLE Parcels (
id int IDENTITY (1,1) NOT NULL,
ParcelNo varchar(5),
Description varchar(max)
-- Ranking AS (SELECT COUNT(*) FROM Invoices i WHERE i.ParcelID = id)
);
CREATE TABLE Invoices (
id int IDENTITY (1,1) NOT NULL,
InvoiceNumber varchar(5),
ParcelID int FOREIGN KEY REFERENCES Parcels(id)
);
ALTER TABLE Parcels ADD Ranking AS (SELECT COUNT(*) FROM Invoices i WHERE i.ParcelID = id);
INSERT INTO Parcels
(ParcelNo)
VALUES
('P0001'),
('P0001'),
('P0002'),
('P0003');
INSERT INTO Invoices
(InvoiceNumber, ParcelID)
VALUES
('INV01', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0001')),
('INV02', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0001')),
('INV03', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0002')),
('INV04', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0002')),
('INV05', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0003')),
('INV06', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0003'));
On the other hand, if you really want all the data in a single table, then try this:
-- Second approach
CREATE TABLE TableA (
Invoicenumber varchar(5),
ParcelNo varchar(5),
Ranking AS (SELECT COUNT(*) FROM TableA a WHERE a.ParcelNo = ParcelNo)
)
Some notes:
Both of my approaches assume that by ranking, you mean that you want a count of how many invoices are in a parcel.
My first approach has a circular reference, because the Invoices table has a foreign key into the Parcels table, but the Parcels table tabulates information from the Invoices table. That's why I commented out the calculated field in the first table, then added the calculated field back in after creating both tables.
Notice that I capitalized all SQL keywords (except the types such as varchar). It's easier to read SQL if you either go with all caps or no caps for an entire query.
Notice my semicolons at the end of each logical break. Semi-colons are technically optional, but a lot of folks consider using them to be good practice.
For my first approach, I'm using a foreign key. You can read more about those here.
Because my first approach split the table into 2 tables, I needed to somehow know the id of the Parcels table when populating the Invoices table, even though the ids are given by the database (so I can't know them ahead of time). Those select statements accomplish that.
My syntax should work with SQL Server, but no necessarily with any other DBMS. That's because calculated fields are not ANSI standard.
I have two tables. One is a category ID, the other one is a product table. I would like to count how many products of each category ID, and the query is below.
SELECT hkgg_emall_goods_class.gc_id, COUNT(*) as productcount
FROM hkgg_emall_goods_class
LEFT JOIN hkgg_emall_goods
ON hkgg_emall_goods.gc_id=hkgg_emall_goods_class.gc_id GROUP BY hkgg_emall_goods_class.gc_id ;
It shows what I want, except the query shows some rows to have count of 1 even they have no products associated, and some row as 1 count when they actually have one product associated.
I want your advice on
1) how to solve this problem
2) I have added the gc_productcount column in the category table. How can I insert the count query into the gc_productcount column for every row?
INSERT INTO `hkgg_emall_goods_class.gc_productcount`
This query is not working well when I put it in front of the select count query.
P.S. I have browsed the other thread in stackoverflow, but luck is not good enough to browse a similar solution.
Thank you in advance.
Assuming hkgg_emall_goods table has a primary or at least a unique key, that's what you want to count. i.e. you don't want to COUNT(*), you want to COUNT(hkgg_emall_goods.id).
So assuming that primary key is hkgg_emall_goods.id then your query will look like this:
SELECT
hgc.gc_id,
COUNT(hg.id) AS productcount
FROM hkgg_emall_goods_class hgc
LEFT JOIN hkgg_emall_goods hg ON hg.gc_id = hgc.gc_id
GROUP BY
hgc.gc_id
I got a question that I need some clarification. Say I have two tables. 1 is a transaction table and another is a product table. The table structure & example looks something like the below. Note Table1 brings in one of the column from Table2 for matching purposes.
Table1
TransactionID,ProductID1,ProductID2,Date
(productID1 and productID2 are the same)
Table2
ProductID2,TransactionCOUNTforthatDay
I want to find out the count/occurence of all/a particular product transaction from table1 (i.e, the amount of transaction say for the 1st of APRIL) and take that result and insert it into the table2 - TransactionCOUNTforthatDay column based on the ProductID.
How can I do this when both the tables aren't identical?
Always getting SQL error. Please advise. Thank you.
INSERT INTO Table2 (product_id,CountTransactionDAYOFMONTH)
SELECT product_id,
COUNT(product_id) as CountTransactionDAYOFMONTH
FROM Table1
GROUP BY TransactionID,
product_id,
DateCreated
I have a website with products where some products are duplicated, and the duplication is only because sometimes the same products goes under more than one categories. I just want the unique columns of the product, not the duplicate (that has another ID and another Category_id). I know the problem could be solved if the table was normalized, but I didn't develop these tables and I can't redesign the database now.
So basically I'm trying to something that logically looks like this (but the code below still gets the repeated products):
SELECT id
FROM `website_products`
WHERE p_name_en
IN (
SELECT DISTINCT p_name_en
FROM `website_products`
)
Do you just want:
select distinct id
from website_products
Or are you trying to get distinct product names with a single id:
select p_name_en, id
from website_products wp
group by p_name_en;
You Can Try like this,,,
SELECT id
FROM `website_products
group by p_name_en
I have a products table which contains duplicate products by a column id_str and not id. We use the id_str to track each product. This is what I tried thus far:
Created a temp table and truncated it, then ran the following query
INSERT INTO products_temp SELECT DISTINCT id_str, id, title, url, image_url, long_descr, mp_seller_name, customer_rating, curr_item_price, base_item_price, item_num, rank, created_at, updated_at, published, publish_ready, categories, feed_id, category_names, last_published_at, canonical_url, is_curated, pr_attributes, gender, rating, stock_status, uploadedimage_file_name, updated_by, backfill_text, image_width, image_height, list_source, list_source_time, list_category, list_type, list_image, list_name, list_domain, notes, street_date, list_product_rank, created_by from products
And this moved everything over however when I searched the new table for duplicate id_str's:
SELECT id_str, COUNT(*) C FROM PRODUCTS GROUP BY id_str HAVING C > 1
I get the same result as I do on the original table. What am i missing?
one or more of the other columns cause the rows being inserted to be unique.
you are only testing the id_str in the count query,.
Using SELECT DISTINCT only removes duplicated entire rows. It doesn't remove a row if only one of the values is the same and the others are different.
Assuming that id is unique, try this instead:
INSERT INTO products_temp
SELECT id_str, id, title, url, -- etc
FROM products
WHERE id IN (SELECT MIN(id) FROM products GROUP BY id_str)
Try SELECT id_str, COUNT(*) C FROM PRODUCTS_TEMP GROUP BY id_str HAVING C > 1
In your case you are selecting again from the original table.
This is the simplest way I found to find and delete duplicates:
Note: Because of a bug with the InnoDB engine, for this to work you need to change your engine to MyISAM:
ALTER TABLE <table_name> ENGINE MyISAM
then add a unique index to the column you are trying to find dup's in using ignore:
ALTER IGNORE TABLE <table_name> ADD UNIQUE INDEX(`<column_name>`)
and change your db engine back:
ALTER TABLE <table_name> ENGINE InnoDB
and if you want you can delete the index you just created, but I would suggest also looking into what caused the duplicates in the first place.