Limit query by sum of values - mysql

I have a mysql table, transactions, with fields id, transactionType, quantity, price etc. I want to limit records by the cumulative sum of one column. So I want to pull out all the transactions until the cumulative quantity reaches my variable (here <=50).
What am I doing wrong?
SET #qsum := 0;
SELECT *
FROM (
SELECT *, (#qsum := #qsum + quantity) AS cumulative_quantity
FROM transactions ORDER BY id DESC
) transactions
WHERE
transactionType = 'buy'
AND typeID = 10
AND cumulative_quantity <= 50

Try this way
SET #qsum := 0;
SELECT *
FROM (
SELECT *, (#qsum := #qsum + quantity) AS cumulative_quantity
FROM transactions
WHERE transactionType = 'buy'
AND typeID = 10
AND cumulative_quantity <= 50
ORDER BY id DESC
) transaction

Related

SQL SUM then count?

Table Historical_Inventory
Column: Date, Prod_ID, WHStock, Stock_Allocated
I want to count the amount of times a products (WHstock - stock allocated) <= 0 between date x and y where Prod_ID = "id1"
Any ideas?
I was going along the lines of
SELECT Count `Prod_ID`
, sum((`WHStock`-`Stock_Allocated`)) as Stock
from Historic_Inventory
WHERE `Date` Between '2018-04-01'and '2018-08-01'
AND Stock <= 0
But not working very well..
I think you want:
SELECT COUNT(*)
FROM (SELECT Prod_ID, SUM(WHStock - Stock_Allocated) as Stock
FROM Historic_Inventory
WHERE `Date` Between '2018-04-01' and '2018-08-01'
GROUP BY Prod_ID
) x
WHERE Stock <= 0;
Hmmm. . . this counts the number of products where the value is negative.
Perhaps you want:
select hi.*
(#stock := #stock + (WHStock - Stock_Allocated)) as stock
from (select hi.*
from historic_inventory hi
where prod_id = ?
order by date
) hi cross join
(select #stock := 0) params
having stock < 0;
Try this:
SELECT Count(*)
FROM
(SELECT SUM((`WHStock`-`Stock_Allocated`)) AS Stock
FROM Historic_Inventory
WHERE `Date` Between '2018-04-01'and '2018-08-01') AS t
WHERE t.Stock <= 0

How to get 100 record of each customer in a single query

I have a location table now I have to keep only 100 record for each customer and have to move rest of them to another server.
using this query We can get customers list
SELECT user_id FROM user_location_history WHERE (TIMESTAMPDIFF(DAY,FROM_UNIXTIME(location_date/1000),SYSDATE()) < 30) GROUP BY user_id HAVING COUNT(1) < 100
Now suppose we have a list of customer like
I am trying to write a single query to get all the record for each customer which is greater then 100.
125452
412555
554114
258471
Please suggest ....
This will get the latest 100 records of each customer
SELECT user_id, substring_index(group_concat(sample_id ORDER BY sample_id DESC SEPARATOR ','), ',', 100) limit100, FROM user_location_history GROUP BY user_id ;
Try this query it generates a row number for each record :-
set #num := 0, #group := '';
select *
from
(
select user_id,
#num := if(#group = `user_id`, #num + 1, 1) as row_number,
#group := `user_id` as dummy
from user_location_history
WHERE (TIMESTAMPDIFF(DAY,FROM_UNIXTIME(location_date/1000),SYSDATE()) < 30)
) as x
where x.row_number <= 100;

MySQL query to get count of current month and last month to get percentage of growth

What im trying to achieve is to get the current count and last month count so i can do a formula to get the growth percentage
(CountCurrent - CountLastMonth) / CountLastMonth
My table has the following fields
activity, upload_date
This is the query im trying now.
SELECT
Y.CurrentMonth, Y.CountCurrent,
Z.LastMonth, Z.CountLastMonth
FROM
(SELECT
upload_date,
activity,
DATE_FORMAT(upload_date,'%M %Y') AS CurrentMonth,
COUNT(activity) AS CountCurrent
FROM appmaster
WHERE activity = 'com.google.test'
GROUP BY DATE_FORMAT(upload_date,'%m%y'))
Y INNER JOIN
(SELECT
activity,
DATE_FORMAT(upload_date,'%M %Y') AS CurrentMonth2,
DATE_FORMAT(upload_date - INTERVAL 1 MONTH,'%M %Y') AS LastMonth,
COUNT(activity) AS CountLastMonth
FROM appmaster
WHERE activity = 'com.google.test'
GROUP BY DATE_FORMAT(upload_date - INTERVAL 1 MONTH,'%m%y'))
Z ON Z.CurrentMonth2 = Y.CurrentMonth
GROUP BY DATE_FORMAT(upload_date,'%Y%m')
ORDER BY DATE_FORMAT(upload_date,'%Y%m')
My CurrentMonth, CountCurrent and LastMonth work fine. But the CountLastMonth is coming out the same as CountCurrent.
I was trying this before and it would give me everything but the CountLastMonth
SELECT b.CurrentMonth, sum(b.CountCurrent), b.LastMonth
FROM (SELECT DATE(a.upload_date - INTERVAL 1 MONTH) AS LastMonth, DATE(a.upload_date) AS CurrentMonth, COUNT(a.activity) AS CountCurrent
FROM appmaster a WHERE a.activity = 'com.google.android.googlequicksearchbox'
group BY MONTH(a.upload_date)) AS b
group BY MONTH(b.CurrentMonth)
No temporary table required:
SELECT
a.ym,
CASE #totals
WHEN 0 THEN 0
ELSE (a.totals - #totals) / #totals
END increment,
#totals := a.totals totals
FROM
(
SELECT
EXTRACT(YEAR_MONTH FROM upload_date) ym,
COUNT(1) AS totals
FROM
appmaster
WHERE
activity = 'com.google.test'
GROUP BY ym -- no ORDER BY required
) a
CROSS JOIN (SELECT #totals := 0) x
Maybe there's a simpler way to do this, using a little trick with user variables.
First, you need to write a query that groups your data by month; I'll store it in a temp table to ease things a bit:
drop table if exists temp_count;
create temporary table temp_count
select last_day(upload_date) as month -- A little trick to get
-- the last day of the month
, count(activity) as count_current
-- Add any other fields or expressions you need
from app_master
-- Add the needed joins
-- Include any WHERE conditions here
group by last_day(upload_date);
-- Let's add an index to this temp table... add any indexes you may need
alter table temp_count
add index idx_month(month);
And now, let's use this temp table to get what you need:
select a.month
, #count_last as count_last -- This is the value of the user variable
-- before reassigning it
, (a.count_current - #count_last) / #count_last as increment
, #count_last := a.count_current -- Here the variable is updated with the
-- current value
from
( -- This subquery is used to initialize the user variable
select #count_last := 0
) as init
, temp_count as a
-- It's important to order the data, otherwise God knows what may happen ;)
order by a.month;
Hope this helps
#Rental number Growth per month -- This is the example for monthly growth where "Total count of activity per month" is concerned -- This answer was developed based on Barranka answer and credit goes to him.
SELECT
a.YM,
CASE #Num_of_Rentals
WHEN 0 THEN 0
ELSE (a.Num_of_Rentals - #Num_of_Rentals) / #Num_of_Rentals
END increment,
#Num_of_Rentals := a.Num_of_Rentals Num_of_Rentals
FROM
(
SELECT
LEFT(rental_date,7) YM,
COUNT(rental_id) AS Num_of_Rentals
FROM
rental
GROUP BY ym -- no ORDER BY required
) a
CROSS JOIN (SELECT #Num_of_Rentals := 0) x;
-- OR
SELECT
a.YM,
CASE #Num_of_Rentals
WHEN 0 THEN 0
ELSE (a.Num_of_Rentals - #Num_of_Rentals) / #Num_of_Rentals
END increment,
#Num_of_Rentals := a.Num_of_Rentals Num_of_Rentals
FROM
(
SELECT
LEFT(rental_date,7) YM,
COUNT(1) AS Num_of_Rentals
FROM
rental
GROUP BY ym -- no ORDER BY required
) a
CROSS JOIN (SELECT #Num_of_Rentals := 0) x;
Revenue growth over each month - This is based on the answer provided by Barranka but it is suitable for Monthly revenue growth:
SELECT
a.YM,
CASE #Revenue
WHEN 0 THEN 0
ELSE (a.Revenue - #Revenue) / #Revenue
END Increment,
#Revenue := a.Revenue Revenue
FROM
(
SELECT
LEFT(payment_date, 7) YM,
SUM(amount) AS Revenue -- Toatl is SUM of Amount
FROM
payment
GROUP BY YM -- no ORDER BY required
) a
CROSS JOIN (SELECT #Revenue := 0) x
;
SELECT
a.YM,
CASE #Revenue
WHEN 0 THEN 0
ELSE (a.Revenue - #Revenue) / #Revenue
END Increment,
#Revenue := a.Revenue Revenue
FROM
(
SELECT
EXTRACT(YEAR_MONTH FROM payment_date) YM,
SUM(amount) AS Revenue
FROM
payment
GROUP BY YM -- no ORDER BY required
) a
CROSS JOIN (SELECT #Revenue := 0) x
;

MySQL: Where this is true, if not, then this

My query:
SELECT *
FROM ranks
WHERE
(price = 25.00 AND accumulate = 0)
OR
(price <= (SELECT SUM(amount) FROM donations WHERE username = 'username' AND amount IN (SELECT price FROM ranks WHERE accumulate = 1)))
ORDER BY price
DESC LIMIT 1
Basically I want to return the first where clause if it finds a match, otherwise return the second clause.
This query will work
SELECT *
FROM ranks
WHERE price = 25.00 AND accumulate = 0
UNION ALL
SELECT *
FROM ranks
WHERE NOT EXISTS(SELECT *
FROM ranks
WHERE price = 25.00 AND accumulate = 0)
AND (price <= (SELECT SUM(amount) FROM donations WHERE username = 'username' AND amount IN (SELECT price FROM ranks WHERE accumulate = 1)))
ORDER BY price
DESC LIMIT 1
Try this query with IF
SELECT *
FROM ranks
WHERE if(price = 25.00,accumulate = 0, price <= (SELECT
SUM(amount)
FROM donations
WHERE username = 'username'
AND amount IN(SELECT
price
FROM ranks
WHERE accumulate = 1)))
ORDER BY price DESC
LIMIT 1

Include an additional counter in the MySQL result set

Can I include an additional counter in a MySQL result set? I have the following query which gives me two columns back. I need an additional column (only in the result) indicating the row of each line in the result set.
select orderid, round(sum(unitprice * quantity),2) as value
from order_details
group by orderid
order by 2 desc
limit 10
I need something like the following:
10865 1 17250.00
11030 2 16321.90
10981 3 15810.00
10372 4 12281.20
10424 5 11493.20
Try this:
SET #counter = 0;
Select sub.*
FROM
(
select orderid, (#counter := #counter +1) as counter,
round(sum(unitprice * quantity),2) as value
from order_details
group by orderid
) sub
order by 2 desc
Try following
SET #counter = 0;
select orderid, (#counter:= #counter + 1) as counter, round(sum(unitprice * quantity),2) as value
from order_details
group by orderid
order by 3 desc
limit 10
Hope it helps...
Based on the two answers I managed to get the following:
SET #counter = 0;
Select sub.orderid,sub.value,(#counter := #counter +1) as counter
FROM
(
select orderid,
round(sum(unitprice * quantity),2) as value
from order_details
group by orderid
) sub
order by 2 desc
limit 10
The original answers showed the IDs from the inner query resulting in larger ints with huge gaps. Using the modification I get just the '1 to x' range that I need for my pgfplots LaTeX plot.