SQL - Avg value by year - mysql

create table sales(
invoiceid int primary key,
deptid int,
salesamt decimal(10,2),
salesdate datetime
);
insert into sales values (101, 2, 2111.02, '20160102');
insert into sales values (102, 2, 421.00, '20160202');
insert into sales values (103, 2, 675.00, '20160202');
insert into sales values (104, 2, 4355.00, '20160302');
insert into sales values (105, 2, 975.00, '20160304');
insert into sales values (106, 2, 1021.00, '20160402');
insert into sales values (107, 2, 2106.00, '20160425');
insert into sales values (108, 2, 2799.81, '20160501');
insert into sales values (109, 2, 4335.75, '20160502');
insert into sales values (110, 2, 12006.00, '20160521');
insert into sales values (111, 2, 5220.00, '20160602');
insert into sales values (112, 2, 7198.02, '20160618');
insert into sales values (113, 2, 4795.00, '20160625');
insert into sales values (114, 2, 5341.00, '20160706');
insert into sales values (115, 2, 5795.00, '20160718');
insert into sales values (116, 2, 6400.00, '20160725');
insert into sales values (117, 2, 14795.00, '20160812');
insert into sales values (118, 2, 43395.00, '20160825');
insert into sales values (119, 2, 47595.00, '20160914');
insert into sales values (120, 2, 46795.00, '20160930');
insert into sales values (121, 2, 6223.00, '20161010');
insert into sales values (122, 2, 7702.00, '20161012');
insert into sales values (123, 2, 11292.00, '20161107');
insert into sales values (124, 2, 33211.00, '20161126');
insert into sales values (125, 2, 16430.00, '20161206');
insert into sales values (126, 2, 87010.00, '20161221');
insert into sales values (127, 2, 2111.02, '20170102');
insert into sales values (128, 2, 421.00, '20170202');
insert into sales values (129, 2, 675.00, '20170202');
insert into sales values (130, 2, 4355.00, '20170302');
insert into sales values (131, 2, 975.00, '20170304');
insert into sales values (132, 2, 1021.00, '20170402');
insert into sales values (133, 2, 2106.00, '20170425');
insert into sales values (134, 2, 2799.81, '20170501');
insert into sales values (135, 2, 4335.75, '20170502');
insert into sales values (136, 2, 12006.00, '20170521');
insert into sales values (137, 2, 5220.00, '20170602');
insert into sales values (138, 2, 7198.02, '20170618');
insert into sales values (139, 2, 4795.00, '20170625');
insert into sales values (140, 2, 5341.00, '20170706');
insert into sales values (141, 2, 7004.00, '20170718');
insert into sales values (142, 2, 14991.00, '20170725');
insert into sales values (143, 2, 34076.00, '20170812');
insert into sales values (144, 2, 47950.00, '20170825');
insert into sales values (145, 2, 40795.00, '20170914');
insert into sales values (146, 2, 41795.00, '20170930');
insert into sales values (147, 2, 47295.00, '20171010');
insert into sales values (148, 2, 47395.00, '20171012');
insert into sales values (149, 2, 41795.00, '20171107');
insert into sales values (150, 2, 47895.00, '20161126');
insert into sales values (151, 2, 87666.00, '20161206');
insert into sales values (152, 2, 9401.00, '20161221');
For the above data I am trying to determine the average sales considering only year. For example the data as only 2 years, so the average is total/2. One way of doing is may get distinct years & total sum from subquery and then average. I am exploring if there is a better way of doing it. Any pointers are helpful. Thanks in advance.

Do you just want aggregation?
select year(salesdate) salesyear, avg(salesamt) avg_sales
from sales
group by year(salesdate)
order by salesyear
This produces one row per year, with the average value of salesamt.
On the other hand, if you want the average of yearly sales, then you can use two levels of aggregation:
select avg(salesamt) yearly_avg_sales
from (select sum(salesamt) salesamt from sales group by year(salesdate)) t
I think the query you had in mind was:
select sum(salesamt) / count(distinct year(salesdate)) yearly_avg_sales
from sales
It produces the same result as the second query. You would need to test both queries against your data to see which performs better.

select year(salesdate) as yearofsales , avg(salesamt) as salesavg from sales group by year(salesdate) order by yearofsales

Related

Lead window function in mysql to find sales

Given this table. I would like to know for each day how many different customers made a sale on date t and and t+1.
-- create a table
CREATE TABLE sales_t(
id INTEGER PRIMARY KEY,
d_date date NOT NULL,
sale INT NOT NULL,
customer_n INT NOT NULL
);
-- insert some values
INSERT INTO sales_t VALUES (1, '2021-06-30', 12, 1);
INSERT INTO sales_t VALUES (2, '2021-06-30', 22, 5);
INSERT INTO sales_t VALUES (3, '2021-06-30', 111, 3);
INSERT INTO sales_t VALUES (4, '2021-07-01', 27, 1);
INSERT INTO sales_t VALUES (5, '2021-07-01', 90, 4);
INSERT INTO sales_t VALUES (6, '2021-07-01', 33, 3);
INSERT INTO sales_t VALUES (6, '2021-07-01', 332, 3);
The result for date 2021-06-30 is 2 because customer 1 and 3 made a sale in t and t+1.
Date sale_t_and_t+1
.....................................
2021-06-30 2
2021-07-01 0
Use LEAD() window function for each distinct combination of date and customer to create a flag which will be 1 if the customer is present in both days or 0 if not and aggregate:
SELECT d_date, COALESCE(SUM(flag), 0) `sale_t_and_t+1`
FROM (
SELECT DISTINCT d_date, customer_n,
LEAD(d_date) OVER (PARTITION BY customer_n ORDER BY d_date) = d_date + INTERVAL 1 DAY flag
FROM sales_t
) t
GROUP BY d_date;
See the demo.

Write a query that returns the sum of the sales by month and year - SQL

I'm stuck on getting the sales months to add together instead of show up as separate lines. Here's the question:
Write a query that returns the sum of the sales by month and year. There will be only two columns returned “Month Year” and “Sales”. Format the Sales with a dollar sign and two decimal places. List the sales amount high to low.
My query:
SELECT date_format(salesdate, '%M,%Y') AS 'Month Year', CONCAT('$', salesamt) AS 'Sales'
FROM sales
GROUP BY invoiceid
ORDER BY salesamt DESC;
I'm pretty sure the group by is the issue, but none of the other columns work. Any help would be greatly appreciated.
Table:
CREATE TABLE sales (
invoiceid INT PRIMARY KEY,
depid INT,
salesamt DECIMAL(10,2),
salesdate DATETIME
);
Values:
insert into sales values (101, 2, 2111.02, '20160102');
insert into sales values (102, 2, 421.00, '20160202');
insert into sales values (103, 2, 675.00, '20160202');
insert into sales values (104, 2, 4355.00, '20160302');
insert into sales values (105, 2, 975.00, '20160304');
insert into sales values (106, 2, 1021.00, '20160402');
insert into sales values (107, 2, 2106.00, '20160425');
insert into sales values (108, 2, 2799.81, '20160501');
insert into sales values (109, 2, 4335.75, '20160502');
insert into sales values (110, 2, 12006.00, '20160521');
insert into sales values (111, 2, 5220.00, '20160602');
insert into sales values (112, 2, 7198.02, '20160618');
insert into sales values (113, 2, 4795.00, '20160625');
insert into sales values (114, 2, 5341.00, '20160706');
insert into sales values (115, 2, 5795.00, '20160718');
insert into sales values (116, 2, 6400.00, '20160725');
insert into sales values (117, 2, 14795.00, '20160812');
insert into sales values (118, 2, 43395.00, '20160825');
insert into sales values (119, 2, 47595.00, '20160914');
insert into sales values (120, 2, 46795.00, '20160930');
insert into sales values (121, 2, 6223.00, '20161010');
insert into sales values (122, 2, 7702.00, '20161012');
insert into sales values (123, 2, 11292.00, '20161107');
insert into sales values (124, 2, 33211.00, '20161126');
insert into sales values (125, 2, 16430.00, '20161206');
insert into sales values (126, 2, 87010.00, '20161221');
insert into sales values (127, 2, 2111.02, '20170102');
insert into sales values (128, 2, 421.00, '20170202');
insert into sales values (129, 2, 675.00, '20170202');
insert into sales values (130, 2, 4355.00, '20170302');
insert into sales values (131, 2, 975.00, '20170304');
insert into sales values (132, 2, 1021.00, '20170402');
insert into sales values (133, 2, 2106.00, '20170425');
insert into sales values (134, 2, 2799.81, '20170501');
insert into sales values (135, 2, 4335.75, '20170502');
insert into sales values (136, 2, 12006.00, '20170521');
insert into sales values (137, 2, 5220.00, '20170602');
insert into sales values (138, 2, 7198.02, '20170618');
insert into sales values (139, 2, 4795.00, '20170625');
insert into sales values (140, 2, 5341.00, '20170706');
insert into sales values (141, 2, 7004.00, '20170718');
insert into sales values (142, 2, 14991.00, '20170725');
insert into sales values (143, 2, 34076.00, '20170812');
insert into sales values (144, 2, 47950.00, '20170825');
insert into sales values (145, 2, 40795.00, '20170914');
insert into sales values (146, 2, 41795.00, '20170930');
insert into sales values (147, 2, 47295.00, '20171010');
insert into sales values (148, 2, 47395.00, '20171012');
insert into sales values (149, 2, 41795.00, '20171107');
insert into sales values (150, 2, 47895.00, '20161126');
insert into sales values (151, 2, 87666.00, '20161206');
insert into sales values (152, 2, 9401.00, '20161221');
Try this
select concat('$',sum(a.Sales)) sum, a.Month_Year
from
(SELECT date_format(salesdate, '%M,%Y') AS 'Month_Year', salesamt AS 'Sales' FROM sales) a
group by a.Month_Year
order by sum(a.Sales) desc;
About your query...
I think the invoiceId is unique.
It is the reason why your group by is useless.

MYSQL Unknown Column in Query

I am looking to fetch sum of transactions grouping them by item ID. I am able to get desired result fron below query in Oracle DB but the same does not work in MYSQL.
Below error is what I am getting:
Unknown column 'tran.itemid' in 'on clause'
SELECT tran.itemid,
(SELECT SUM(tranitm.quandity)
FROM transactions_item tranitm
JOIN transactions tr
ON(tr.id = tranitm.transid and tranitm.itemid = tran.itemid)
where TR.TRANSTYPE = 1) Purchases,
(SELECT SUM(tranitm.quandity)
FROM transactions_item tranitm
JOIN transactions tr
ON(tr.id = tranitm.transid and tranitm.itemid = tran.itemid)
where TR.TRANSTYPE = 2 ) Sales,
(SELECT SUM(tranitm.quandity)
FROM transactions_item tranitm
JOIN transactions tr
ON(tr.id = tranitm.transid and tranitm.itemid = tran.itemid)
where TR.TRANSTYPE = 3 ) PurchasesRtn,
(SELECT SUM(tranitm.quandity)
FROM transactions_item tranitm
JOIN transactions tr
ON(tr.id = tranitm.transid and tranitm.itemid = tran.itemid)
where TR.TRANSTYPE = 4) SalesRtn
FROM transactions_item tran
GROUP BY tran.itemid
Schema :
CREATE TABLE transactions
( id INT, transtype INT,fromledger INT,
ledgerid INT,agentid INT, quandity FLOAT,rate FLOAT);
CREATE TABLE transactions_item
(transid INT, itemid INT,quandity FLOAT,rate FLOAT);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (1, 1, 1, 1, 1, 100, 1000);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (2, 2, 1, 1, 1, 10, 1200);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (3, 3, 1, 1, 1, 50, 1500);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (4, 4, 1, 1, 1, 120, 1300);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (5, 1, 1, 1, 1, 10, 1100);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (6, 2, 1, 1, 1, 12, 1400);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (7, 3, 1, 1, 1, 130, 1550);
INsert into transactions (id, transtype, fromledger, ledgerid, agentid,
quandity, rate) values (8, 4, 1, 1, 1, 110, 1700);
INsert into transactions_item (transid, itemid,quandity,rate) values (1, 1, 100, 1000);
INsert into transactions_item (transid, itemid,quandity,rate) values (2, 1, 10, 1200);
INsert into transactions_item (transid, itemid,quandity,rate) values (3, 1, 50, 1500);
INsert into transactions_item (transid, itemid,quandity,rate) values (4, 1, 120, 1300);
INsert into transactions_item (transid, itemid,quandity,rate) values (5, 1, 10, 1100);
INsert into transactions_item (transid, itemid,quandity,rate) values (6, 1, 12, 1400);
INsert into transactions_item (transid, itemid,quandity,rate) values (7, 1, 130, 1550);
INsert into transactions_item (transid, itemid,quandity,rate) values (8, 1, 110, 1700);
INsert into transactions_item (transid, itemid,quandity,rate) values (1, 2, 100, 1000);
INsert into transactions_item (transid, itemid,quandity,rate) values (2, 2, 10, 1200);
INsert into transactions_item (transid, itemid,quandity,rate) values (3, 2, 50, 1500);
INsert into transactions_item (transid, itemid,quandity,rate) values (4, 2, 120, 1300);
INsert into transactions_item (transid, itemid,quandity,rate) values (5, 2, 10, 1100);
INsert into transactions_item (transid, itemid,quandity,rate) values (6, 2, 12, 1400);
INsert into transactions_item (transid, itemid,quandity,rate) values (7, 2, 130, 1550);
INsert into transactions_item (transid, itemid,quandity,rate) values (8, 2, 110, 1700);
The ON clauses in the subqueries should be used to relate the tables being joined. Conditions that aren't part of the join should be in WHERE.
But there's a better way to do this than all those correlated subqueries.
SELECT tran.itemid,
SUM(IF(tr.transtype = 1, tran.quandity, 0)) AS Purchases,
SUM(IF(tr.transtype = 2, tran.quandity, 0)) AS Sales,
SUM(IF(tr.transtype = 3, tran.quandity, 0)) AS PurchasesRtn,
SUM(IF(tr.transtype = 4, tran.quandity, 0)) AS SalesRtn
FROM transactions_item AS tran
JOIN transactions AS tr ON tran.transid = tr.id
GROUP BY tran.itemid
DEMO
See need to return two sets of data with two different where clauses

Age range computation where each country has at least two distinct ages of the individuals

For my dataset here, I want to create result such that for those countries (which have at least two distinct Ages), I could summarise the Age Range.
CREATE TABLE Employees(
ID int (3) NOT NULL,
Name varchar (50) NOT NULL,
Age int (3) NOT NULL,
Nationality varchar (50) NOT NULL
);
INSERT INTO Employees
(ID, Name, Age, Nationality)
VALUES
(1, 'CHIN YEN', '19', 'China'),
(2, 'MIKE PEARL', '21', 'United Kingdom'),
(3, 'GREEN FIELD', '45', 'Nethernalnds'),
(4, 'DEWANE PAUL', '57', 'Canada'),
(5, 'MATTS', '32', 'Australia'),
(6, 'PLANK OTO', '51', 'France'),
(7, 'Manish Kumar', '42', 'India'),
(8, 'Matts', '55', 'USA'),
(9, 'Mahesh Kumar', '32', 'USA'),
(10, 'Chin Yen', '21', 'Japan');
And what I was trying to do is:
SELECT Nationality,
Max(Age) - Min(Age) AS Age_Range
FROM Employees;
I think you just need a group by:
SELECT Nationality,
Max(Age) - Min(Age) AS Age_Range
FROM Employees
GROUP BY Nationality;
You might want to add HAVING Age_Range > 0.
To construct a query which will return age range for only those countries in which at least two individuals with distinct non-zero ages exist, following can be approach.
SELECT Nationality,
Max(Age) - Min(NULLIF(Age,0)) AS Age_Range
FROM Employees
GROUP BY Nationality
having Max(Age) - Min(NULLIF(Age,0)) > 0
what is does is that for any individual has age=0 , nullif convert its age into NULL which is then ignored by aggregate function MIN.
I have changed the data you shared as below.
INSERT INTO Employees
(ID, Name, Age, Nationality)
VALUES
(1, 'CHIN YEN', 0, 'United Kingdom'),
(2, 'MIKE PEARL', 21, 'United Kingdom'),
(3, 'GREEN FIELD', 45, 'Nethernalnds'),
(4, 'DEWANE PAUL', 57, 'Nethernalnds'),
(5, 'MATTS', 0, 'Nethernalnds'),
(6, 'PLANK OTO', 51, 'France'),
(7, 'Manish Kumar', 42, 'India'),
(8, 'Matts', 55, 'USA'),
(9, 'Mahesh Kumar', 32, 'USA'),
(10, 'Chin Yen', 21, 'Japan');
Below is the result as expected using the query i shared.
You can check DEMO here

Selecting only the first two items from and order

I need you help regarding something, i have 3 tables ORDERS, ORDER_ITEM, ORDER_ITEM_LINE.
CREATE TABLE orders
(`id` int, `date` datetime)
;
INSERT INTO orders
(`id`, `date`)
VALUES
(78, '2017-01-03 00:00:00'),
(79, '2017-02-03 00:00:00'),
(80, '2017-03-03 00:00:00'),
(81, '2017-04-03 00:00:00'),
(82, '2017-05-03 00:00:00'),
(83, '2017-06-03 00:00:00'),
(84, '2017-07-03 00:00:00')
;
CREATE TABLE order_item
(`id` int, `fk_o_id` int, `sku` int)
;
INSERT INTO order_item
(`id`, `fk_o_id`, `sku`)
VALUES
(10, 78, 123),
(11, 79, 124),
(12, 79, 125),
(13, 80, 126),
(14, 82, 127),
(15, 82, 128),
(16, 82, 129)
;
CREATE TABLE order_item_line
(`id` int, `fk_oi_id` int, `line_id` int)
;
INSERT INTO order_item_line
(`id`, `fk_oi_id`, `line_id`)
VALUES
(33, 10, 1),
(34, 11, 1),
(35, 12, 2),
(36, 13, 1),
(37, 14, 1),
(38, 15, 2),
(39, 16, 3)
;
I would like to display all orders with 2 or more than 2 items but only first two so it will be line_id - 1 and 2.
The outcome should look like:
Outcome
If you have any ideas, thank you in advance.
To get the result you require, you will need to create another table. In this example I created a table called TESTQUERY and inserted data to count how many times the orders id appeared
Table creation
CREATE TABLE TESTQUERY
(`id` int, `count` int)
Data into the test table
INSERT INTO TESTQUERY
(
SELECT o.id, COUNT(o.id) as count FROM orders o
JOIN order_item oi ON oi.fk_o_id = o.id
JOIN order_item_line oil ON oil.fk_oi_id = oi.id
GROUP BY o.id
)
I then queried against all for databases using the query below and it returned your desired outcome
SELECT o.id, oi.sku, oil.line_id FROM orders o
JOIN order_item oi ON oi.fk_o_id = o.id
JOIN order_item_line oil ON oil.fk_oi_id = oi.id
JOIN TESTQUERY t ON t.id = o.id
WHERE t.count > 1 AND oil.line_id < 3
I hope this helps