I have a quite large products table and I need some smart solution to find out which products are (in woocommerce terms) Simple, Variable, and Variation.
In the example table below, ids 6 and 7 are Simple products (they don't have children), 1 and 4 are Variable products (they have children), and 2,3,5 are Variations (they are children).
id
item_id
parent_id
other_columns
1
aaa
aaa
...
2
aaa-1
aaa
...
3
aaa-2
aaa
...
4
bbb
bbb
...
5
bbb-1
bbb
...
6
ccc
ccc
...
7
ddd
ddd
...
My goal is to first get Simple products, then get Variable products and import them and lastly get Variations and import them to the existing parent Variable products.
I have a solution for Simple products:
SELECT *
FROM (
SELECT *
FROM $table_name
WHERE item_id = parent_id
GROUP BY parent_id
HAVING COUNT(*) = 1
) AS ONLY_ONCE
I've tried similar for the Variable products (count(*) > 1), but it doesn't work...
For Variation I have:
SELECT *
FROM $table_name
WHERE item_id != parent_id
Simple products - select all where item_id is equal with parent_id, and parent_id occurs only once.
Variable products - select all where item_id is equal with parent_id and parent_id occurs more than once.
Variation - select all where item_id and parent_id are not equal.
How could I write those three queries, especially the second one? any help is appreciated.
SELECT *,
CASE WHEN EXISTS ( SELECT NULL
FROM test t2
WHERE t2.parent_id = t1.item_id
AND t2.item_id <> t2.parent_id )
THEN 'Variable'
WHEN NOT EXISTS ( SELECT NULL
FROM test t3
WHERE t3.parent_id = t1.item_id )
THEN 'Variation'
ELSE 'Simple'
END Category
FROM test t1;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=b3215cbb3febbdbc4132ee00aac2ad8e
I would solve this as a combination of SQL queries and php code.
At first I would get all parents (variable products) and fetch the results. In PHP then loop through the results and use the parents id as parameter for the next query.
Related
I am still a php/mysql newbie and I am working on mysql table relationship concept and i am having an issue with using mysql count in multiple table. Here is my db structure.
**product table**
id product_name product_img groupeid
1 Sneaker Mark sneaker_adi.png 1
2 bag Eric bageric.png 2
3 Sneaker Etoi sneakeretoi.jpg 1
**groupe table**
group_id group_name
1 men
2 women
**category table**
catid catname
1 sneaker-shoes
2 bag-woman
**productcategory table**
prod_id cat_ID
1 1
2 2
3 1
What i want to do is to determine the number of sneaker-shoes using mysql.
We can see that the number of sneaker-shoes in the db is 2.
But how can i use **count()** in these multiple tables.
I tried like this;
$sql = "SELECT COUNT(*) product.id,product_name,catname FROM product INNER JOIN productcategory ON product.id = prod_id INNER JOIN category ON catid = cat_ID WHERE catname='sneaker-shoes'";
i got error like:
Fatal error: Call to a member function execute() on a non-object in C:\wamp\www\kbashopping\Homme\index.php on line 32
Hope i exposed the issue clearly, any help and assistance will be appreciate
Thanks
If you are looking only for the count, mention only the count phrase in the Select clause.
Change :
SELECT COUNT(*) product.id,product_name,catname FROM
to :
SELECT COUNT(product.id) FROM
SELECT count (pc.cat_ID) FROM productcategory pc inner join category c on c.catid = pc.cat_ID where c.catname = 'sneaker shoes';
This will build a temporary table in mysql that joins category and product category but only including results where the catname is sneaker shoes. Then it selects a column to run the count operation on, and returns the result of count.
In my database i have categories, offers and coupons. i would like to count offers and coupons that exist in each category. when i use union it returns the same category twice.
i have the below query that returning same category rows with same name. i try to use union distinct but it does not work.
(SELECT
cat1.id AS cat1id, cat1.title AS title,
count(offers.id) AS offercounter
FROM cat1
INNER JOIN offers
ON offers.category=cat1.title
GROUP BY cat1.id
order by cat1.order)
UNION
(SELECT
cat1.id AS cat1id, cat1.title AS title,
count(coupons.id) AS couponscounter
FROM cat1
INNER JOIN coupons
ON coupons.category=cat1.title
GROUP BY cat1.id
order by cat1.order)
the result
cat1id title offercounter
2 Food 5388
23 Clothes 6000(this is offers)
32 Technology 499
40 Clothes 4(this is coupons)
i would like clothes to be (offercounter + couponscounter).
example: clothes=6004 and not two different rows
the desired result would be :
cat1id title offercounter
2 Food 5388
23 Clothes 6004(offers+coupons)
32 Technology 499
Alternative avoiding unions or sub queries is to use a couple of LEFT OUTER JOINS, and count the distinct ids from each table:-
SELECT cat1.id AS cat1id,
cat1.title AS title,
COUNT(DISTINCT offers.id) + COUNT(DISTINCT coupons.id) AS offercounter
FROM cat1
LEFT OUTER JOIN offers ON offers.category = cat1.title
LEFT OUTER JOIN coupons ON coupons.category = cat1.title
GROUP BY cat1.id AS cat1id,
cat1.title AS title
EDIT
A left outer join will return a row of nulls when there is no matching row.
For example if there was a row on cat1 with a matching row on offers but no matching row on coupons then the resulting row would consist of the row from cat1, the row from offers and the fields from coupons would be null.
This SQL will get every combination of matching rows. So if you had:-
cat1 fields offers fields coupons fields
id title id category id category
1 fred 99 fred 77 fred
1 fred 99 fred 88 fred
1 fred 100 fred 77 fred
1 fred 100 fred 88 fred
2 burt 120 fred NULL NULL
2 burt 121 fred NULL NULL
Hence the count uses DISTINCT to only could each id within a category once. As COUNT(field name) only counts non null values, with this example data for the 2nd category the count from coupons will be 0.
Union returns distinct rows. Your returned rows are distinct indeed. What you need to do to get your desired result is aggregate after unioning.
select min(cat1id) as cat1id, title, sum(offercounter) as offercounter
from
(your_query) as subquery
group by title
replace your_query with your existing query
Why don't you simple sum up the offercounter and use group by with order by cat1id.
SELECT cat1id,title,sum(offercounter) as offercounter
FROM offers GROUP BY title ORDER BY cat1id
View : SQL Fiddle
Output :
cat1id title offercounter
2 Food 5388
23 Clothes 6004
32 Technology 499
May be this can help.
SELECT cat1.id AS cat1id, cat1.title AS title ,((SELECT COUNT(offers.id) FROM offers WHERE offers.category=cat1.title)+(SELECT COUNT(coupons.id) FROM coupons WHERE coupons.category=cat1.title)) AS offercounter
FROM cat1
I currently have an Array in PHP with product numbers. Lets call that products.
In my database I have a table containing combinations of product numbers and the price that belongs to that product.
Problem: My Array can hold duplicate entries if for instance article #1 is ordered twice.
If I use a query like
SELECT SUM(price) FROM articles WHERE article_number IN (products)
the duplicate entry of 1 get discarded. The query I am looking for gives the sum of 10 + 10 + 12.5 + 9.95.
Is there a way to do this within MySQL?
As a clarification to my data:
products = [1, 1, 2, 3];
articles| article_number | price
__________________________________
| 1 | 10.0
| 2 | 12.5
| 3 | 9.95
Thank you :)
winmutt has a solid answer. However, if you don't have such a table to to join with then you could build your query like so:
select sum (p) from (
(select price as p from articles where article_number = 1)
union all
(select price as p from articles where article_number = 1)
union all
(select price as p from articles where article_number = 2)
union all
(select price as p from articles where article_number = 3)
) s
If your products were in a table you could do a simple JOIN:
SELECT SUM(price) FROM articles JOIN products on article_number=product_number
I thought there might be an easier way of doing this in SQL. I solved it in PHP by querying all the prices of the array's products and then in iterating over my Array in PHP to sum up the price there.
Here's the table structure
id | name | parent_id
1 fruit 0
2 apple 1
3 banana 1
4 orange 1
5 vegetable 0
6 carrot 5
7 tomato 5
I need get every row where a parent_id is 0, but I also need to to set an array on each row which is equal to 0 with the name of all it's children.
So I would have something like:
id = 1, name = fruit, children = [apple, banana, orange]
I'm aware there are better table structures but I must use the table structure stated.
I've tried getting all rows from the db then looping through them, if parent_id = 0 then push that to an array, otherwise it's a child so find parent in array and add it to that.
But there must be a better way?
I thinks you should use:
SELECT pr.id, pr.name, (
SELECT GROUP_CONCAT(name) FROM test as ch WHERE ch.parent_id = pr.id GROUP BY ch.parent_id
) AS children
FROM test as pr
WHERE parent_id = 0
Without thinking about performance or beauty:
SELECT t.id, name, (
SELECT GROUP_CONCAT(name) FROM table WHERE parent_id = t.id GROUP BY parent_id
) AS children
FROM table t
WHERE parent_id = 0
Avoiding a sub query, just using a self join the following should do it:-
SELECT t1.id, t1.name, GROUP_CONCAT(CONCAT('name:', t2.name))
FROM test t1
LEFT OUTER JOIN test t2
ON t1.id = t2.parent_id
WHERE t1.parent_id = 0
GROUP BY t1.id, t1.name
SQL fiddle for it:-
http://www.sqlfiddle.com/#!2/d4479a/1
I had come across a similar issue, where I had to fetch all subordinates of a user in a recursive manner.
We wrote a function where we loop through each of the child records recursively until we reach the final subordinate. We keep on concatenating the subbordinates we find in each loop.
Hope through this you can think of a solution and resolve your problem.
I have a table named PRODUCTS with 3 columns for three different categories, i want to select all products which have any of the 3 values in any of the 3 columns.
What i'm trying to do is show related products based on any of the 3 categories.
Example table:
id,name,cat1,cat2,cat3
1,Keyboard,2,8,4
2,Mouse,2,NULL,NULL
3,Monitor,16,2,NULL
Let's supose i'm viewing ITEM id=1, i want to do a query to show the other 2 products that have category number 2 in any of the 3 columns.
How do I do that?
Thank you very much,
Andres
SELECT * FROM table_name WHERE id != 1 AND (cat1 = 2 OR cat2 = 2 OR cat3 = 2)
So, for any given ID, find the other "siblings" that have that same category as the chosen one, in their categories?
select id as chosen_id, p1.cat as p1_cat, p2.cat as p2_cat, p3.cat as p3_cat
from products p1, products p2, products p3
where
p1.cat = p2.cat
and
p1.cat = p3.cat
// and various other qualifications like, it's not a repeat
p1.id != p2.id
p1.id != p3.id
p2.id != p3.id
etc.
// you can also do join products p3 on p3.cat = p1.cat instead of
// the verbose way I did it
BTW this is a bad idea performance-wise. Best done programmatically and not in SQL.Any time you're dealing with cursor-ish queries like this, just do it with arrays in code, not in SQL