MySQL: SUM data from two different tables - mysql

I have a db for a menu which tracks clicks on it. The menu has categories and subcategories and I'm trying to get the amount of clicks for each category but in the db, the clicks will register to the subcategory if the item is in one, otherwise the clicks are counted in the category. I have a query that will get clicks for all subcategories (category_type 3) but I need to add them with the clicks from their parent category (category_type 2). There is a table called CategoryHierarchy that maps each category to it's parent category. This is what I have:
SELECT IFNULL(SUM(`MenuEntryAnalytics`.`opened`), 0) AS `clicks`,
`Categories`.`id`,
`Categories`.`name`,
`Categories`.`category_type`,
`CategoryHierarchy`.`parent_id` AS `parent`
FROM `MenuEntryAnalytics`
INNER JOIN `MenuEntries`
ON `MenuEntryAnalytics`.`menu_entry_id` = `MenuEntries`.`id`
LEFT JOIN `MenuEntryToCategory`
ON `MenuEntryAnalytics`.`menu_entry_id` = `MenuEntryToCategory`.`menu_entry_id`
RIGHT JOIN `Categories`
ON `MenuEntryToCategory`.`category_id` = `Categories`.`id`
RIGHT JOIN `CategoryHierarchy`
ON `Categories`.`id` = `CategoryHierarchy`.`category_id`
WHERE `Categories`.`category_type` = 3
GROUP BY `id`;
Results:
clicks id name type parent
=============================================
2032 3 Appetizers 3 2
455 4 Salads 3 2
680 6 Sandwiches 3 5
424 7 Burgers 3 5
584 9 Pizza 3 8
466 10 Kids Menu 3 8
1445 12 Soda 3 11
1089 13 Signature Cocktails 3 11
391 14 Bottled Beer 3 11
167 15 Wine 3 11
0 17 Events 3 16
0 18 Sponsors 3 16
186 19 Dessert 3 11
621 26 Restaurants 3 22
263 27 Bars 3 22
112 28 Services 3 25
254 29 Amenities 3 25
67 30 Exclusive Benefits 3 25
190 31 Area Attractions 3 24
14 32 Entertainment 3 24
2 33 Shopping 3 24
117 34 Transportation & Tours 3 24
471 35 Mixed Drinks 3 11
541 36 Draft Beer 3 11
if I GROUP BY parent then I can get most of what I need (all the clicks from subcategories of each category) but this doesn't get the clicks counted towards categories (as opposed to subcategories, i.e. category_type 2). I'm stuck trying to add that part in, all I can think of is using a subquery but there's no way of identifying which category I'm looking at, thus I get a subquery with multiple rows.
PS I do not have permission to restructure the db.

Since the parent ID is in the same namespace as the ID, you can simply use IFNULL to pick the parent if it exists, or otherwise the ID. And use that as your grouping strategy.
You may also want to select the same data out as an actual column.
GROUP BY
IFNULL(CategoryHierarchy.parent_id, Categories.id, CategoryHierarchy.parent_id)

Related

Sum of all child and assign to parent in hierarchical data in MySql

I have a 2 Mysql tables like 1.Product(This table is hierarchical or recursive) and 2.Sales table in this will store sale id and product id. I need to show parent product with the sum of all hierarchical child product.
Product table having data like,
id name parent_id
1 Necklace NULL
2 Ring NULL
3 Earing NULL
4 Choker 1
5 Long Necklace 1
6 Short Necklace 1
7 2-Line 5
8 3-Line 5
9 Mango 5
10 Green 7
11 Red 7
12 White 7
13 Stud 3
Sales table will have data like,
id product_id no_of_pcs weight rate
1 10 5 40 35000
2 12 8 50 50000
3 9 2 20 25000
4 6 1 8 25000
5 13 2 16 22000
Now I'm trying the result as,
Product sale_pcs tot_pcs sale_wt sale_rate
1 Necklace 16 118 135000
3 Earing 2 16 22000
Now I'm using mysql query inside php recursive function by using product table. By using this even recursive function all the products need to check with sales table. This will happening performance issue. Could you please help any one to solve this issue whether this possible by doing in query itself

Evenly distribute rows withing a group

Suppose I have a table ITEMBANKITEMASSOCIATION as
ID FKITEMBANKID FKITEMID
1 1 100
2 2 101
3 2 102
4 2 103
5 2 104
6 3 105
7 3 106
8 4 107
9 4 108
10 4 109
11 4 110
12 4 111
I want to select 10 rows but rows must to evenly distributed within FKITEMBANKID. That Means suppose I want 10 rows to select within 4 item banks, so 10/4 gives 2 items from each Item banks. This I have achieved by query
SELECT ITEMBANKITEMASSOCIATION.*
FROM ITEMBANKITEMASSOCIATION INNER JOIN (
SELECT inIBA.FKITEMBANKID, GROUP_CONCAT(inIBA.FKITEMID) grouped_year
FROM ITEMBANKITEMASSOCIATION inIBA
GROUP BY inIBA.FKITEMBANKID) group_max
ON ITEMBANKITEMASSOCIATION.FKITEMBANKID = group_max.FKITEMBANKID
AND FIND_IN_SET(ITEMBANKITEMASSOCIATION.FKITEMID, grouped_year) between 1 and 2
ORDER BY
ITEMBANKITEMASSOCIATION.FKITEMBANKID DESC;
Fiddle is here
Result of this query gives only 7 rows, because this query select rows from each group (itembank) between 1 and 2. Still 3 rows are need to be pulled, how I can pull remaining 3 rows by distributing it in available itembanks? Available itembanks means after fetching first 7 exclude the pulled items and re-distribute within remaining banks.

SQL Find All user that have two history in a certain order

I'm looking for a SQL request that I can't find in internet (and I didn't found a solution myself).
I have two different table user and history and a table user_history that link the two tables.
For example :
USER
id name
1 John
2 Edie
3 France
4 Gabriel
5 Ellen
History
id date_entered type
1 2017-07-01 36
2 2017-07-02 52
3 2017-07-03 25
4 2017-07-04 69
5 2017-07-05 85
6 2017-07-06 74
7 2017-07-07 45
8 2017-07-08 85
9 2017-07-09 25
10 2017-07-10 78
USER_HISTORY
id id_user id_history
1 1 1
2 1 2
3 1 3
4 1 4
5 2 5
6 2 6
7 1 7
8 1 8
9 2 9
10 1 10
In this example, all history are made by user 1 and 2 (user 2 have history 5,6 and 9).
So the question is :
What is the SQL request that get me all the users that have in their history an history type 25 and then some days LATER an history type 85 ?
In this example, only user 1 (John) is ok because he has a history type 25 on 2017-07-03 and then an history type 85 on 2017-07-08.
User 2 (Edie) is not ok because even if he has an history 25 and 85, the first one was 85 and the 25.
Is that clear ?
Can you help me please ?
You need to JOIN twice with HISTORY table, e.g.:
SELECT h1.id_user
FROM (
SELECT u.id_user, h.date_entered
FROM user_history u
JOIN history h ON u.id_history = h.id
WHERE h.type = 25) h1
JOIN (
SELECT u.id_user, h.date_entered
FROM user_history u
JOIN history h ON u.id_history = h.id
WHERE h.type = 85
) h2 ON h1.id_user = h2.id_user
WHERE h1.date_entered < h2.date_entered;
Here's the SQL Fiddle.

How to select 3 row per category in MySQL?

I have a table which have a lot of data, it's have a category ID and postId, I need to read 3 new post per category with same CatID.
it's not duplicate of the question suggest by other people. Please check that in my question the postid catid can be anything when in duplicate question it's calculate before running query.
What I have written is
SELECT
MAX(` postid `) AS p1,
` catid ` AS c1
FROM
` postcategory `
GROUP BY
` catid
I can put 2 other query in it union distinct but it will make a query a lot big. Is there any good way to do this in MySQL. What I am looking for reading 3 postId (maximum) belong to same category.
postId catId
------ --------
9 3
15 3
16 3
17 3
18 3
19 5
20 8
21 6
22 8
23 6
46 6
46 8
26 3
25 3
27 5
28 3
37 6
39 10
40 6
41 6
42 6
43 6
44 5
45 11
63 6
64 5
65 6
66 6
68 6
You can read 3 new post from each category Using the below query.
SELECT
p1.postId,
p1.catId
FROM
postcategory p1
JOIN postcategory p2 ON p1.catId = p2.catId
AND p2.postId >= p1.postId
GROUP BY
p1.postId,
p1.catId
HAVING
COUNT(*) <= 3
ORDER BY
catId,
postId
Here you can see the Live Demo
Output:

Get the latest 3 nodes foreach taxonomy term in one query

I am trying to setup a query to get the 3 most recent nodes (nid) foreach taxonomy term (tid). Is this possible to set up on one query?
Here are how my tables are set up (not displaying full table info)
taxonomy_index (Holds the taxonomy ids that are associated to a node)
nid tid
1 20
1 21
1 22
2 20
2 21
3 23
3 24
4 20
4 21
5 20
5 21
5 22
5 23
6 20
6 21
6 24
7 20
7 21
8 20
8 21
9 20
9 21
9 22
9 23
.....
node (node information)
nid title created
1 Article One 1105350260
2 Article Two 1105350259
3 Article Three 1105350261
4 Article Four 1105350280
5 Article Five 1105350290
6 Article Six 1105350290
.....
I'm envisioning a result like this if I wanted to see the latest 3 nodes for tids: 20, 21, 22:
tid nid
20 1
20 2
20 4
21 1
21 2
21 4
22 1
22 5
22 9
Is this possible in one query?
You can try follwing query:-
SELECT t.tid, t.nid
FROM taxonomy_index s
WHERE (SELECT COUNT(*)
FROM taxonomy_index f
WHERE f.tid = s.tid
AND f.nid <= s.nid
) <= 3;
here i have used <=3 #cond, in case if any tid dont have 3 records the it will fetch 2 or 1, whichever is more.