Sql Dynamic Column for Position of AgentID - mysql

I had Collection Table for Agents
Agentid logintime AmountReceived
1 2013/10/01 00:10:10 10000
1 2013/10/01 17:23:10 200
1 2013/10/01 00:30:41 3000
2 2013/10/02 05:10:52 1000
3 2013/10/02 09:10:25 2000
3 2013/10/03 10:10:18 2000
2 2013/10/03 13:10:35 7000
I want a query that should display the output as
Agentid Amount Rank
1 13200 1
2 8000 2
3 4000 3
Displaying UI:
agentID : 1
Today: 13200 (Today amount yesturady amount should be place in this month)
Month: Need to display month total amount(30 days amount last month amount in this year)
Year : Need to display year total amount(12 months amount)

Try this:
SELECT Agentid,SUM(AmountReceived) as Amount,#rownum := #rownum + 1 AS Rank
FROM TableName,(SELECT #rownum := 0) r
GROUP BY AgentID
ORDER BY SUM(AmountReceived) DESC
Result:
AGENTID AMOUNT RANK
1 13200 1
2 8000 2
3 4000 3
See result in SQL Fiddle.
EDIT:
For year-wise and month-wise result:
SELECT Agentid,year(logintime) as Year,monthname(logintime) as Month,SUM(AmountReceived) as Amount,#rownum := #rownum + 1 AS Rank
FROM TableName,(SELECT #rownum := 0) r
GROUP BY AgentID,year(logintime),monthname(logintime)
ORDER BY SUM(AmountReceived) DESC
Result:
AGENTID YEAR MONTH AMOUNT RANK
1 2013 October 13200 1
2 2013 October 8000 2
3 2013 October 4000 3
Result in SQL Fiddle.

Related

How to cummulative sum in MySql with grupBy and interval?

Table Sales
date id_product total sales
2018-10-01 1 40
2019-09-01 1 20
2019-11-01 1 5
2019-12-01 1 40
2020-01-01 1 10
2020-02-01 1 15
2020-03-01 1 20
2020-08-01 1 10
2021-01-01 1 5
2021-02-01 1 8
2021-04-01 1 12
Table Product
id name
1 Book
2 Pen
How to query in MySql to get the number (serial/sequential number) and the total cumulative sales with an interval of 3 years to get results like this?
number name date sum_sales cummulative_sales
1 Book 2018 40 40
2 Book 2019 65 105
3 Book 2020 55 160
4 Book 2021 25 145
Assuming you are running MySQL 8+, you may try using SUM as an analytic function:
SELECT
ROW_NUMBER() OVER (PARTITION BY p.name ORDER BY YEAR(s.date)) number,
p.name,
YEAR(s.date) AS date,
SUM(s.total_sales) AS sum_sales,
SUM(SUM(s.total_sales)) OVER (PARTITION BY p.name ORDER BY YEAR(s.date)) AS cummulative_sales
FROM Sales s
INNER JOIN Product p
ON p.id = s.id_product
GROUP BY
p.name,
YEAR(s.date)
ORDER BY
p.name,
YEAR(s.date);
Using MySQL 5.7, this will give you a sum and a cumulative sum of sales in a window of 3 years.
SELECT (#row = #row + 1) AS number, name, YEAR(date) AS date,
SUM(total_sales) as sum_sales,
iF(
#window > 0,
#cummulative_sales := #cummulative_sales + SUM(total_sales),
#cummulative_sales := SUM(total_sales)
) AS cummulative_sales,
#window := #window + 1,
#window := #window % 3
FROM Sales
JOIN Product ON Sales.id_product = Product.id,
(
SELECT #row := 0, #cummulative_sales := 0, #window := 0
) as a
GROUP BY name, YEAR(date);

Getting top 5 records and its count per month

I'm using phpmyadmin.
I have a table call malicioussite. It include 2 column call region which contain ISO-3166-1 alpha-2 code such as GB, US and adddate contain the timestamp of it.
SELECT region, COUNT(*) AS total
FROM malicioussite
GROUP BY region
ORDER BY COUNT(*) DESC LIMIT 5
It gave me the top 5 record of my table and it's correct:
region total
JP 7
US 6
RU 5
CN 4
DE 3
And now i want to get the top 5 record and its count per month of last 6 months.
SELECT region, MONTH(adddate) as Month, count(*) as Total
FROM malicioussite
where adddate BETWEEN DATE_FORMAT(NOW()-INTERVAL 5 MONTH, '%Y-%m-01 00:00:00') AND DATE_FORMAT(LAST_DAY(NOW()), '%Y-%m-%d 23:59:59')
GROUP BY YEAR(adddate), MONTH(adddate), region
It gave me all of the region and the count per month of last 6 months.
region Month Total
AQ 9 1
AR 10 1
KR 11 1
GB 12 1
HK 12 1
JP 12 1
US 12 1
AS 1 1
HK 1 1
JP 1 2
US 1 1
CN 2 4
DE 2 3
JP 2 4
RU 2 5
US 2 4
It's partly correct but what i want is only the top 5 region's such as below:
region Month Total
JP 12 1
JP 1 2
JP 2 4
US 12 1
US 1 1
US 2 4
RU 2 5
CN 2 4
DE 2 3
Is there any way that should solve my issue?
You've done all the work, just need to add a condition with subquery.
SELECT region, MONTH(adddate) as Month, count(*) as Total
FROM malicioussite
where adddate BETWEEN DATE_FORMAT(NOW()-INTERVAL 5 MONTH, '%Y-%m-01 00:00:00')
AND DATE_FORMAT(LAST_DAY(NOW()), '%Y-%m-%d 23:59:59')
AND region IN (SELECT region
FROM malicioussite
GROUP BY region
ORDER BY COUNT(*) DESC LIMIT 5)
GROUP BY YEAR(adddate), MONTH(adddate), region
Or with a join
SELECT m.region, MONTH(adddate) as Month, count(*) as Total
FROM malicioussite m
JOIN (SELECT region
FROM malicioussite
GROUP BY region
ORDER BY COUNT(*) DESC LIMIT 5) as top_reg
ON top_reg.region = m.region
where adddate BETWEEN DATE_FORMAT(NOW()-INTERVAL 5 MONTH, '%Y-%m-01 00:00:00')
AND DATE_FORMAT(LAST_DAY(NOW()), '%Y-%m-%d 23:59:59')
GROUP BY YEAR(adddate), MONTH(adddate), m.region

mysql group by query with average calculation

id originator revenue date
-- ---------- ------- ----------
1 acme 1 2013-09-15
2 acme 0 2013-09-15
3 acme 4 2013-09-14
4 acme 6 2013-09-13
5 acme -6 2013-09-13
6 hello 1 2013-09-15
7 hello 0 2013-09-14
8 hello 2 2013-09-13
9 hello 5 2013-09-14
I have the above table . And I would like to add the ranking column based on the revenue generated by the originator based on the revenue for last 3 days
the fields to be displayed as below:
originator revenue toprank
---------- ------- -------
hello 8 1
acme 5 2
2) And based on the above data , i would like to calculate the avg revenue generated based on the following criteria
If the sum of total revenue for the same date is 0 ( zero) then it should not be counted with calculating the average.
a) avg value for originator acme should be sum of revenue/count(no of dates where the revenue is non zero value) so (4+1)/2 i.e 2.5
b) avg value for originator hello should be sum of revenue/count(no of dates where the revenue is non zero value) so (5+2+1)/3 i.e 2.6666
originator revenue toprank avg(3 days)
---------- ------- ------- -----------
hello 8 1 2.6666
acme 5 2 2.5
To ignore a row when averaging, give AVG a null value. The NULLIF function is good for this.
The ranking is problematic in MySQL. It doesn't support analytic functions that make this a bit easier to do in Oracle, MySQL, Teradata, etc. The most common workaround is to use a counter variable, and that requires an ordered set of rows, which means the total revenue must be calculated in an inner query.
SELECT originator, TotalRev, Avg3Days, #rnk := #rnk + 1 AS TopRank
FROM (
SELECT
originator,
SUM(revenue) AS TotalRev,
AVG(NULLIF(revenue, 0)) AS Avg3Days
FROM myTable
GROUP BY originator
ORDER BY TotalRev DESC
) Tots, (SELECT #rnk := 0) Ranks
If you want to get the values for the last 3 days from today's date, try something like this:
SET #rank=0;
select originator, rev, #rank:=#rank+1 AS rank, avg
FROM
(select originator, sum(revenue) as rev,
AVG(NULLIF(revenue, 0)) as avg
FROM t1
WHERE date >= DATE_ADD(CURDATE(), INTERVAL -3 DAY)
group by originator
order by 2 desc) as t2;
SQL Fiddle..
EDITED:
If you want to get the values for the last 3 days from the nearest date, try this:
SET #rank=0;
select originator, rev, #rank:=#rank+1 AS rank, avg
from
(select originator, sum(revenue) as rev,
AVG(NULLIF(revenue, 0)) as avg
from t1
WHERE date >= DATE_ADD((select max(date) from t1), INTERVAL -3 DAY)
group by originator
order by 2 desc) as t2;
SQL Fiddle..

Compute outstanding amounts in MySQL

I am having an issue with a SELECT command in MySQL. I have a database of securities exchanged daily with maturity from 1 to 1000 days (>1 mio rows). I would like to get the outstanding amount per day (and possibly per category). To give an example, suppose this is my initial dataset:
DATE VALUE MATURITY
1 10 3
1 15 2
2 10 1
3 5 1
I would like to get the following output
DATE OUTSTANDING_AMOUNT
1 25
2 35
3 15
Outstanding amount is calculated as the total of securities exchanged still 'alive'. That means, in day 2 there is a new exchange for 10 and two old exchanges (10 and 15) still outstanding as their maturity is longer than one day, for a total outstanding amount of 35 on day 2. In day 3 instead there is a new exchange for 5 and an old exchange from day 1 of 10. That is, 15 of outstanding amount.
Here's a more visual explanation:
Monday Tuesday Wednesday
10 10 10 (Day 1, Value 10, matures in 3 days)
15 15 (Day 1, 15, 2 days)
10 (Day 2, 10, 1 day)
5 (Day 3, 5, 3 days with remainder not shown)
-------------------------------------
25 35 15 (Outstanding amount on each day)
Is there a simple way to get this result?
First of all in the main subquery we find SUM of all Values for current date. Then add to them values from previous dates according their MATURITY (the second subquery).
SQLFiddle demo
select T1.Date,T1.SumValue+
IFNULL((select SUM(VALUE)
from T
where
T1.Date between
T.Date+1 and T.Date+Maturity-1 )
,0)
FROM
(
select Date,
sum(Value) as SumValue
from T
group by Date
) T1
order by DATE
I'm not sure if this is what you are looking for, perhaps if you give more detail
select
DATE
,sum(VALUE) as OUTSTANDING_AMOUNT
from
NameOfYourTable
group by
DATE
Order by
DATE
I hope this helps
Each date considers each row for inclusion in the summation of value
SELECT d.DATE, SUM(m.VALUE) AS OUTSTANDING_AMOUNT
FROM yourTable AS d JOIN yourtable AS m ON d.DATE >= m.MATURITY
GROUP BY d.DATE
ORDER BY d.DATE
A possible solution with a tally (numbers) table
SELECT date, SUM(value) outstanding_amount
FROM
(
SELECT date + maturity - n.n date, value, maturity
FROM table1 t JOIN
(
SELECT 1 n UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5
) n ON n.n <= maturity
) q
GROUP BY date
Output:
| DATE | OUTSTANDING_AMOUNT |
-----------------------------
| 1 | 25 |
| 2 | 35 |
| 3 | 15 |
Here is SQLFiddle demo

SQL query "Find the article that has generated most income?"

I want to make a SQL query that shows me the article that generated most income. (in a shop)
Table = orderrader
rownumber articlenumber ordernumber price amount
1 11 1 8624 3
2 6 1 4794 2
3 17 1 8755 3
4 1 1 7803 1
5 16 1 8987 3
6 10 1 4575 3
7 4 1 8747 1
8 15 1 5439 3
9 11 2 8624 3
10 1 2 7803 1
Following sql statement will return only one articlenumber with max revenue.
Select articlenumber, sum(price*amount) as totalincome
from orderrader
group by articlenumber
order by sum(price*amount) desc LIMIT 1
SELECT articlenumber
FROM orderrader
WHERE (price * amount) = (SELECT MAX(price * amount) FROM orderrader)
This should do the trick, i checked it on my own database. It will give ONLY the one with the highest price*amount
SELECT articlenumber, SUM(price*amount) AS income
FROM table
GROUP BY articlenumber
ORDER BY income DESC
select articlenumber, sum(price*amount) as s from orderrader group by articlenumber order by s desc;