SQL : loop through same table with tree structure data - mysql

I'm on MySQL 8.0.24, and I have a tree structure table named category, it has 3 columns: category_id, parent_id, image.
category_id
image
parent_id
69
68
70
68
71
68
60
57
61
60
62
57
63
62
64
57
65
64
66
57
67
66
68
57
53
52
54
52
55
52
56
52
57
41
58
57
59
58
18
14
19
18
20
18
21
1
22
21
23
22
24
22
25
21
26
25
27
26
28
26
I want to use the resultset of category_id obtained from another query, loop thru each element in the array and try to see if a given parent_id can be matched.
For example, the resultset of category_id is {98, 60, 26}, and I want to find out if any of the 3 elements has a parent_id of 1.
Analysis:
98's parent_id is NULL,
60's parent_id is 57, 41
26's parent_id is 25, 21, 1
Therefore a hit is found.
I tried to understand and use the following SQL from sql loop thru same table, with no luck...
with aa_category(category_id) as (select category_id from aa_category union all select nplus1.category_id from aa_category as nplus1, aa_category where aa_category.category_id = nplus1.parent_id) select category_id from aa_category;
How do I write this SQL?

you can use recursive cte:
with recursive cte as (
select *, category_id originalCategory from category
where category_id in (98, 60, 26)
union all
select c.*, cte.originalCategory from category c
join cte on cte.parent_id = c.category_id
)
select originalCategory,parent_id
from cte
where parent_id = 1
originalCategory
parent_id
26
1
db<>fiddle here

Related

Calculate the number of users based on the below conditions by writing a single query SQL

There are two campaigns running campaign A and Campaign B and list of user ids participated in those two campaign is given below. Calculate the number of users based on the below conditions by writing a single query.
Participated in campaign A
Participated in campaign B
Participated in campaign A only
Participated in campaign B only
Participated in both the campaigns
Participated in either campaign A or Campaign B
Campaign A Campaign B
user_id user_id
91 62
27 11
58 16
50 92
64 17
65 71
54 12
98 37
78 93
24 58
31 54
73 94
63 85
72 30
94 32
20 1
38 48
8 99
43 45
33 46
26 39
100 29
61 49
87 73
84 81
15 88
80 70
77 33
40 55
82
42
56
95
88
I am not able to figure out how to write in single SQL query.
Assuming you have two different tables, you can use union all and aggregation:
select in_a, in_b, count(*) as num_users
from ((select user_id, 1 as in_a, 0 as in_b
from a
) union all
(select user_id, 0 as in_a, 1 as in_b
from b
)
) u
group by in_a, in_b;
This gives you all the information you need. You can use group by in_a, in_b with rollup to get all combinations.
Or, you can summarize this into one row:
select sum(in_a) as in_a, sum(in_b) as in_b,
sum(in_a * (1 - in_b)) as in_a_only,
sum(in_b * (1 - in_a)) as in_b_only,
sum(in_a * in_b) as in_ab
from ((select user_id, 1 as in_a, 0 as in_b
from a
) union all
(select user_id, 0 as in_a, 1 as in_b
from b
)
) u;
Note: These both assume that users are unique in each campaign. If not, just use select distinct or union in the subquery.

Add values in a lists which is a string column in hive

I have a set of data where a columns consists of lists which is of string data type.
Column_A|Column_B
AAA |1 23 56 89 74 52
BBB |63 99 44 2 80 87 58 63
CCC |96 45 23 84 62 74
Here, In the above data I need to add the values in column B as below:
Column_A|Column_B |Column_C
AAA |1 23 56 89 74 52 |295
BBB |63 99 44 2 80 87 58 63|496
CCC |96 45 23 84 62 74 |384
I have used cast function and converted the data type from string to int using the below query.
select Column_A,cast (Column_B as INT) as Column_B from Xyz
But summing the values is a great challenge.
Can someone help me out?
I'm learning RegEx too.. Is there any possibility to use RegEx?
Explode your column using split by space and aggregate.
This is demo in Hive:
with your_data as
(
select Column_A,Column_B from
(
select stack(3,
'AAA','1 23 56 89 74 52',
'BBB','63 99 44 2 80 87 58 63',
'CCC','96 45 23 84 62 74'
) as (Column_A,Column_B)
)s
) --Use your table instead of this CTE
select Column_A,Column_B, sum(cast(b.val_b as int)) as Column_C
from your_data a
lateral view outer explode(split(Column_B,' ')) b as val_b
group by Column_A,Column_B;
Result:
OK
AAA 1 23 56 89 74 52 295
BBB 63 99 44 2 80 87 58 63 496
CCC 96 45 23 84 62 74 384
Time taken: 53.228 seconds, Fetched: 3 row(s)
Alternatively, if the maximum number of elements in the list is fixed, you can do the same without explode, it will work much faster:
create temporary macro cast_value(s string) nvl(cast(s as int),0);
with your_data as
(
select Column_A,Column_B from
(
select stack(3,
'AAA','1 23 56 89 74 52',
'BBB','63 99 44 2 80 87 58 63',
'CCC','96 45 23 84 62 74'
) as (Column_A,Column_B)
)s
) --Use your table instead of this CTE
select Column_A,Column_B,
cast_value(col_B_array[0])+
cast_value(col_B_array[1])+
cast_value(col_B_array[2])+
cast_value(col_B_array[3])+
cast_value(col_B_array[4])+
cast_value(col_B_array[5])+
cast_value(col_B_array[6])+
cast_value(col_B_array[7])+
cast_value(col_B_array[8])+
cast_value(col_B_array[9]) as Column_C
from(
select Column_A,Column_B, split(Column_B,' ') col_B_array
from your_data a
)s
Result:
OK
AAA 1 23 56 89 74 52 295
BBB 63 99 44 2 80 87 58 63 496
CCC 96 45 23 84 62 74 384
Time taken: 0.82 seconds, Fetched: 3 row(s)

Select option of same table - MySQL

I have a table like this:
id product option
1 55 78
2 55 55
3 55 42
4 68 78
5 68 62
6 68 36
7 94 25
8 94 47
9 94 81
How can I select all option where I have option 78 for example? I need to select 55, 42, 62, 36 because product have option 78.
select distinct `option`
from your_table
where product in (select distinct product from your_table where `option` = 78)

Need to fetch a MySQL result

I have following MySQL table structure,
id product_id filter_tag_id
14 1 48
17 3 49
18 10 49
19 10 54
20 11 49
21 11 55
22 12 49
23 12 56
24 9 48
25 9 52
26 6 48
27 6 53
28 7 48
29 7 56
30 8 48
31 8 53
32 13 48
33 13 52
34 14 48
35 14 54
36 14 55
37 15 48
38 15 55
i need to fetch only those product_id's which have same filter_tag_id's,
For example only one product_id (9 and 13) having the same filter_tag_id (48 and 52), so I need to fetch only product_id 9 and 13, I'm trying following query, but no success yet.
select product_id from filter_data where filter_tag_id=52 AND filter_tag_id=48;
select product_id from filter_data where filter_tag_id in (52,48);
First query return no result and second one returning wrong results
Use self-join. It looks like more complicated than GROUP BY, but it is faster than group-by. Because with GROUP BY approach, those which only has 48 or 52 should be groupped that is not unneeded rows.
SELECT t1.product_id
FROM filter_data t1 INNER JOIN filter_data t2 ON t1.product_id = t2.product_id
WHERE t1.filter_tag_id = 48 AND t2.filter_tag_id = 52;
If what you want is to find only product_ids having filter_tag_id values equal to 48 and 52 and nothing else but these two values, then try:
SELECT product_id
FROM mytable
GROUP BY product_id
HAVING COUNT(CASE WHEN filter_tag_id = 48 THEN 1 END) > 0 AND
COUNT(CASE WHEN filter_tag_id = 52 THEN 1 END) > 0 AND
COUNT(CASE WHEN filter_tag_id NOT IN (48,52) THEN 1 END) = 0
Demo here
use GROUP BY
Select product_id,COUNT(DISTINCT filter_tag_id) filter_match
from filter_data where filter_tag_id in (52,48)
GROUP BY product_id
HAVING filter_match = 2
the value of filter_match is count you will pass in condition

Raw SQL query/django query : Get column info by grouping

Following are the tables:
Product Table
25 Tshirt
26 Dress
ProductVariation Table
id product_id variation_id vendor_id
46 26 47 1
47 26 48 1
48 26 49 1
49 27 50 1
Variation Table
id value attribute_id category_id variationinfo_id
47 Female 2 1 17
48 89 3 1 17
49 90 1 1 18
50 #343434 2 1 18
VariationInfo Table
id stock remarks
17 8 remarks1
18 10 remarks2
Attribute Table
id attribute_name
1 size
2 color
3 gender
Category Table
id name parent remarks
1 bla bla bla
Problem scenario:
Product 26 has variation_ids 47, 48, 49. Of these, 47 and 48 have same variationinfo_id 17 and another 49, has 18. For product 26, total stock information is obtained as 18.
However, I need to get distributed stock information for different variationinfo_ids, For example: For variation(VariationTable) 47, 48 with same variationinfo_id of 17, total stock of this variation -> 8 and for 48 with variationinfo_id of 18, total stock of this variation -> 10.
How do I write query for the latter part?
select temp.product_id,temp.variation_ids,temp.variationinfo_id,vi.stock
(select p.product_id,group_concat(v.id) as variation_ids, v.variationinfo_id
from ProductVariation p
join Variation v on p.variation_id=v.id
group by p.product_id,v.variationinfo_id) temp
join VariationInfo vi on temp.variationinfo_id=vi.id
Note: Code is not tested. Small syntactic error may exist.