I've googled and searched here and maybe I don't know the exact way to write the question but can't find an answer...
I need to find the sum of credits from click_stats where source = 'reward' for all users who have claimed at least one of the 3 promo codes AND have the total clicks displayed. There are many more than the 3 but simplifed what I need to try to meet posting criteria.
Tables:
+---------------------------------------------+
| click_stats |
+----+---------+--------+--------+------------+
| ID | Credits | Userid | Source | Clicked |
+----+---------+--------+--------+------------+
| 1 | 10 | jon | reward | 1602216005 |
+----+---------+--------+--------+------------+
| 2 | 5 | bob | reward | 1602216504 |
+----+---------+--------+--------+------------+
| 3 | 5 | jon | reward | 1602216137 |
+----+---------+--------+--------+------------+
| 4 | 5 | bob | reward | 1602216138 |
+----+---------+--------+--------+------------+
| 5 | 10 | jon | reward | 1602216139 |
+----+---------+--------+--------+------------+
| 6 | 5 | jon | reward | 1602216140 |
+----+---------+--------+--------+------------+
| 7 | 10 | bob | reward | 1602216150 |
+----+---------+--------+--------+------------+
| 8 | 10 | jon | reward | 1602216150 |
+----+---------+--------+--------+------------+
+----+---------+--------+--------+------------+
| 9 | 10 | sue | reward | 1602216150 |
+----+---------+--------+--------+------------+
+----+---------+--------+--------+------------+
| 10 | 10 | sue | prize | 1602216150 |
+----+---------+--------+--------+------------+
+-----------------------+
| promo_used |
+----+--------+---------+
| id | userid | promoid |
+----+--------+---------+
| 1 | bob | 1 |
+----+--------+---------+
| 2 | bob | 2 |
+----+--------+---------+
| 3 | bob | 3 |
+----+--------+---------+
| 4 | jon | 1 |
+----+--------+---------+
| 5 | jon | 2 |
+----+--------+---------+
+------------------------+
| promo_codes |
+----+----------+--------+
| id | code | reward |
+----+----------+--------+
| 1 | forever1 | 20 |
+----+----------+--------+
| 2 | novgfy1 | 250 |
+----+----------+--------+
| 3 | novgfy2 | 500 |
+----+----------+--------+
My Query:
SELECT
click_stats.userid as Name,
sum(credits) as TotalClicks
FROM click_stats
JOIN promo_used
ON click_stats.userid = promo_used.userid
JOIN promo_codes
ON promo_used.promoid = promo_codes.id
WHERE
click_stats.source = 'reward'
and FROM_UNIXTIME(clicked) > '2020-10-09'
and (promo_codes.name like '%forever%'
or promo_codes.name like 'novgfy%')
group by
Name
having
TotalClicks > 10
Results when I run my query (returning the total number of clicks * number of promo codes used):
+--------------------+
| Results |
+------+-------------+
| Name | TotalClicks |
+------+-------------+
| bob | 60 |
+------+-------------+
| jon | 80 |
+------+-------------+
Results I am wanting (the total number of clicks only):
+--------------------+
| Expected Results |
+------+-------------+
| Name | TotalClicks |
+------+-------------+
| bob | 20 |
+------+-------------+
| jon | 40 |
+------+-------------+
The problem (I suspect) is that it is summing the click_stats every time it finds a match for promo_codes.name. I just need to know if one of them has been used and then return the total clicks for that user.
Don't join click_stats to the other tables because you will multiply the rows that you get by a factor equal to the number of rows of each user in promo_used.
Instead use the operator IN to filter the users:
SELECT Userid, SUM(Credits) TotalClicks
FROM click_stats
WHERE source = 'reward'
AND FROM_UNIXTIME(clicked) > '2020-10-09'
AND Userid IN (
SELECT pu.Userid
FROM promo_used pu INNER JOIN promo_codes pc
ON pc.id = pu.promoid
WHERE pc.code like '%forever%' OR pc.code like 'novgfy%'
)
GROUP BY Userid
HAVING TotalClicks > 10
Or:
SELECT Userid, SUM(Credits) TotalClicks
FROM click_stats
WHERE source = 'reward'
AND FROM_UNIXTIME(clicked) > '2020-10-09'
AND Userid IN (
SELECT pu.Userid FROM promo_used pu
WHERE EXISTS (
SELECT 1 FROM promo_codes pc
WHERE pc.id = pu.promoid AND (pc.code like '%forever%' OR pc.code like 'novgfy%' )
)
)
GROUP BY Userid
HAVING TotalClicks > 10
See the demo.
Results:
> Userid | TotalClicks
> :----- | ----------:
> bob | 20
> jon | 40
Related
I need to find the sum of credits from click_stats where source = 'reward' for all users who have claimed at least one of the 3 promo codes AND have the total clicks displayed.
Tables:
+---------------------------------------------+
| click_stats |
+----+---------+--------+--------+------------+
| ID | Credits | Userid | Source | Clicked |
+----+---------+--------+--------+------------+
| 1 | 10 | jon | reward | 1602216005 |
| 2 | 5 | bob | reward | 1602216504 |
| 3 | 5 | jon | reward | 1602216137 |
| 4 | 5 | bob | reward | 1602216138 |
| 5 | 10 | jon | reward | 1602216139 |
| 6 | 5 | jon | reward | 1602216140 |
| 7 | 10 | bob | reward | 1602216150 |
| 8 | 10 | jon | reward | 1602216150 |
| 9 | 10 | sue | reward | 1602216150 |
| 10 | 10 | sue | prize | 1602216150 |
+----+---------+--------+--------+------------+
+-----------------------+
| promo_used |
+----+--------+---------+
| id | userid | promoid |
+----+--------+---------+
| 1 | bob | 1 |
+----+--------+---------+
| 2 | bob | 2 |
+----+--------+---------+
| 3 | bob | 3 |
+----+--------+---------+
| 4 | jon | 1 |
+----+--------+---------+
| 5 | jon | 2 |
+----+--------+---------+
+------------------------+
| promo_codes |
+----+----------+--------+
| id | code | reward |
+----+----------+--------+
| 1 | forever1 | 20 |
+----+----------+--------+
| 2 | novgfy1 | 250 |
+----+----------+--------+
| 3 | novgfy2 | 500 |
+----+----------+--------+
My Query:
SELECT
click_stats.userid as Name,
sum(credits) as TotalClicks
FROM click_stats
JOIN promo_used
ON click_stats.userid = promo_used.userid
JOIN promo_codes
ON promo_used.promoid = promo_codes.id
WHERE
click_stats.source = 'reward'
and FROM_UNIXTIME(clicked) > '2020-10-08'
and (promo_codes.name like '%forever%'
or promo_codes.name like 'novgfy%')
group by
Name
having
TotalClicks > 10
Results when I run my query (returning the total number of clicks * number of promo codes used):
+--------------------+
| Results |
+------+-------------+
| Name | TotalClicks |
+------+-------------+
| bob | 60 |
+------+-------------+
| jon | 80 |
+------+-------------+
Results I am wanting (the total number of clicks only):
+--------------------+
| Expected Results |
+------+-------------+
| Name | TotalClicks |
+------+-------------+
| bob | 20 |
+------+-------------+
| jon | 40 |
+------+-------------+
The problem (I suspect) is that it is summing the click_stats every time it finds a match for promo_codes.name. I just need to know if one of them has been used and then return the total clicks for that user.
Your understanding of the problem is correct. The join multiplies the rows whenever a user has more than one of the promo codes, and you end up with the same credit summed several times.
I would recommend exists instead:
select cs.userid as name, sum(cs.credits) as totalclicks
from click_stats cs
where cs.source = 'reward' and exists (
select 1
from promo_used pu
inner join promo_codes pc on pc.id = pu.promoid
where
pu.userid = cs.userid
and (pc.name like '%forever%' or pc.name like 'novgfy%')
)
group by cs.userid
having sum(cs.credits) > 10
I try to write a little voting tool. I have 3 tables: users, locations and votes. votes has 2 foreign keys (user_id and location_id).
Users (example data):
+----+----------+
| id | username |
+----+----------+
| 5 | user1 |
| 7 | user2 |
| 11 | user3 |
| 4 | user4 |
| 12 | user5 |
+----+----------+
Locations:
+----+----------------+
| id | locationname |
+----+----------------+
| 1 | Pasta |
| 2 | Burger |
| 3 | Pizza |
| 4 | Chinese |
| 5 | Thai |
+----+----------------+
Votes:
+----+---------+-------------+------------+
| id | user_id | location_id | date |
+----+---------+-------------+------------+
| 30 | 5 | 1 | 2016-06-30 |
| 31 | 5 | 1 | 2016-07-01 |
| 32 | 7 | 1 | 2016-07-01 |
| 38 | 11 | 2 | 2016-07-01 |
| 39 | 4 | 1 | 2016-07-04 |
| 41 | 12 | 3 | 2016-07-04 |
| 44 | 5 | 4 | 2016-07-04 |
| 46 | 7 | 5 | 2016-07-04 |
+----+---------+-------------+------------+
The keypair date & user is unique so a user can't vote twice.
I now want to have a list like this for CURDATE():
+----------------+----------------+----------------------+
| locationname | Votes | Voters |
+----------------+----------------+----------------------+
| Pasta | 3 | user1, user2, user x |
| Burger | 2 | user3, user4 |
| Pizza | 1 | user5 |
| Chinese | 1 | user6 |
| Thai | 0 | |
+----------------+----------------+----------------------+
How can I solve this? Tried something like that:
SELECT locations.locationname AS location, count(*) AS count, GROUP_CONCAT(users.username SEPARATOR ', ') AS Voters
FROM votes
INNER JOIN locations ON votes.location_id=locations.id
WHERE date = CURDATE()
INNER JOIN users ON users.id=votes.user_id
WHERE location_id = "1" AND date = CURDATE()
GROUP BY location_id
ORDER BY count DESC;
Thanks
A friend of mine showed me how to solve this problem:
SELECT l.id AS locationid, l.locationname, count(username) AS count, GROUP_CONCAT(username SEPARATOR ", ") AS users
FROM locations l
LEFT JOIN votes v
ON v.location_id = l.id AND v.date = CURDATE()
LEFT JOIN users u
ON v.user_id = u.id
GROUP BY locationname
ORDER BY count DESC;
I have the following SQL relationship
user has many games
games has may users
User
----
id | name | age |
__________________
1 | mike | 11 |
2 | jeff | 12 |
3 | jake | 31 |
4 | lemd | 81 |
Game
-----
id | name | time |
_____________________
1 | froyo | 11:10 |
2 | honey | 12:22 |
3 | combb | 13:00 |
4 | lolli | 14:00 |
User_Game
----------
| userid | game_id |
___________________
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
| 4 | 3 |
| 1 | 2 |
| 2 | 4 |
| 2 | 1 |
For each of the users is there a way to get a
list of games that they have played including the number
of games that each user participated in.
Edit
I tried this query
Select User.name, User.age
from User
inner join User_Game
on User.id=User_Game.userid;
However not sure how I could add the count to it
SELECT
userid,
GROUP_CONCAT(game_id) as game_list,
COUNT(*) as total_games
FROM
USER_GAME
GROUP BY
userid;
i want to find solution for my query problem. I need to find the SUM of all priceProduct*quantity and separated with each of productcategory. I have already made a query, but it takes longer time to executed it. this is my query,
SELECT
pb.ProductCategoryID,
pb.ProductCategoryDescription,
(SELECT
SUM((SELECT pd.HPP FROM `price details` pd WHERE pd.ProductID = pdt.ProductID ORDER BY pd.PriceDetailID DESC LIMIT 1)*
(SELECT StockProductBallance FROM `stock product` sp WHERE sp.ProductID = pdt.ProductID ORDER BY sp.StockProductID DESC LIMIT 1))
FROM product pdt
WHERE pdt.ProductCategoryID = pb.ProductCategoryID
) AS Total
FROM `product category` pb
GROUP BY pb.ProductCategoryID
this my example table
table product:
+------+-------+
| id_p | id_pc |
+------+-------+
| 1 | 3 |
| 2 | 4 |
| 3 | 3 |
| 4 | 4 |
+------+-------+
table productcategory:
+-------+---------+
| id_pc | pc_name |
+-------+---------+
| 3 | new_pc |
| 4 | old_pc |
+-------+---------+
table price details:
+---------------+------+-----+
| PriceDetailID | id_p | hpp |
+---------------+------+-----+
| 1 | 1 | 100 |
| 2 | 1 | 110 |
| 3 | 1 | 120 |
| 4 | 2 | 200 |
| 5 | 2 | 210 |
| 6 | 2 | 220 |
+---------------+------+-----+
table stockProduct:
+-----------------+------+---------------+
| id_stockProduct | id_p | stockballance |
+-----------------+------+---------------+
| 1 | 1 | 10 |
| 2 | 1 | 11 |
| 3 | 1 | 12 |
| 4 | 2 | 20 |
| 5 | 2 | 21 |
| 6 | 2 | 22 |
+-----------------+------+---------------+
Really need your help guys, for better query..
I have a complicated ordering issue in my query.
Raw, Unordered Data:
+------+--------+-----------+
| id | job_id | action_id |
+------+--------+-----------+
| 1 | 2 | 1 |
| 2 | 2 | 2 |
| 3 | 1 | 1 |
| 4 | 2 | 3 |
| 5 | 4 | 1 |
| 6 | 1 | 2 |
| 7 | 3 | 1 |
| 8 | 3 | 2 |
| 9 | 4 | 2 |
+------+--------+-----------+
Required Ordering:
+------+--------+-----------+
| id | job_id | action_id |
+------+--------+-----------+
| 7 | 3 | 1 |
| 8 | 3 | 2 |
| | | | * blank lines added for clarity,
| 5 | 4 | 1 | not desired in actual data
| 9 | 4 | 2 |
| | | |
| 3 | 1 | 1 |
| 6 | 1 | 2 |
| | | |
| 1 | 2 | 1 |
| 2 | 2 | 2 |
| 4 | 2 | 3 |
+------+--------+-----------+
The theory behind this ordering:
the largest id is the most recently added entry
the most recent id with action_id of 1
followed by the entries with ascending action_ids that have the same job_id
then the next most recent action_id of 1
ad infinitum
EDIT: I'm not able to add columns to the table in order to aid in sorting, as I've seen in some other solutions to ordering questions.
Any help is greatly appreciated!
My best shot is this:
SELECT * FROM tbl
ORDER BY FIND_IN_SET(job_id,
(SELECT GROUP_CONCAT(job_id ORDER BY ID DESC)
FROM tbl WHERE action_id = 1));
I didn't find a way to do it easily, What do you think of the following code :
select c.id, c.job_id, c.action_id
from (select a.id, a.job_id, a.action_id, min(b.id) as related_id
from myTable a
inner join myTable b
on a.job_id=b.job_id
group by a.job_id) c
group by c.id
order by c.related_id desc, c.action_id