Combining multiple columns in 1 resultset - mysql

I have a table like
CREATE TABLE sales
(`id` int, `date` date, `amount` int(4))
;
insert into sales values (1, '2012-09-01', 200),
(2, '2012-09-01', 300),
(3, '2012-09-02', 400),
(4, '2012-09-02', 500),
(5, '2012-09-02', 600)
I wish to retrieve a row showing the sales for today, and the sales for yesterday
like
Date Today Total sales Yesterday Sales
2012-09-02 1500 500
Tried using something like
SELECT id, date, sum(amount) FROM sales
GROUP BY date;
But it returns the sales day wise. I understand that can be done programmatically, but is there a better way to directly retrieve it from the DB?
sqlfiddle

SELECT id, date(now()) as `date`,
SUM(IF(date(`date`) = date(now()), `amount`, 0)) as TodayTotalSales,
SUM(IF(date(`date`) < date(now()), `amount`, 0)) as OtherDaySales
FROM sales;
http://sqlfiddle.com/#!2/0ef6a/18

You are getting that because Id is different for each record. You have two option now:
Don't retrieve Id and write query like:
SELECT date, sum(amount) FROM sales
GROUP BY date;
Use a join with subquery
SELECT a.ID, a.date, b.amount
FROM sales a, (SELECT date, sum(amount) amount FROM sales
GROUP BY date) b
WHERE a.date = b.date;
Please Note: In option 2, second and third columns will be repeating with same value for each id within a day.

SELECT date, sum(amount), yestersales
FROM sales AS s1,
(SELECT sum(amount) as yestersales, ADDDATE(date, 1) AS yesterdate
FROM sales GROUP BY date) AS s2
WHERE s1.date = s2.yesterdate
GROUP BY date;
Will do what you want, but it's not really very efficient, I don't think. I would personally do it in code.
Selecting the ID doesn't really make much sense here since you're grouping by date.

Related

Trying to count total orders, and unique monthly customers

I am trying to get total amount of orders, and the amount of unique customers in a 30 day timeframe.
I have this table:
order_id, order_date, order_country, customer_id.
(1, '2021/03/04', 'SWE', 1),
(2, '2021/03/01', 'SWE', 1),
(3, '2021/03/01', 'DK', 3),
(4, '2021/03/01', 'DK', 3),
(5, '2021/03/03', 'NOR', 2),
(6, '2021/02/27', 'DK', 3),
(7, '2020/12/30', 'Ger', 4);
I Have tried something like this:
SELECT order_date
, COUNT(order_id) as orderAmount
, COUNT(distinct customer_id) as customerAmount
FROM orders
WHERE order_date BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
GROUP
BY order_date
This gets the total amount of orders per date which is what i want. But it only counts unique customers per date and not monthly, so the same customer comes up multiple times. I have tried small variations of this sql script but can't quite get it to work.
Please check whether it's your desired answer or not.
Schema (MySQL v5.5)
create table orders (order_id int, order_date date, order_country varchar(10), customer_id int);
insert into orders values(1, '2021/03/04', 'SWE', 1);
insert into orders values(2, '2021/03/01', 'SWE', 1);
insert into orders values(3, '2021/03/01', 'DK', 3);
insert into orders values(4, '2021/03/01', 'DK', 3);
insert into orders values(5, '2021/03/03', 'NOR', 2);
insert into orders values(6, '2021/02/27', 'DK', 3);
insert into orders values(7, '2020/12/30', 'Ger', 4);
Query #1
SELECT
o.order_date,COUNT(order_id) as orderAmount
, coalesce(max(Customer_Count),0) as customerAmount
FROM orders o left join (select order_date,count(distinct customer_id)Customer_Count from orders o where
not exists (select customer_id from orders oa where o.customer_id=oa.customer_id and oa.order_date<o.order_date
and oa.order_date > now() - INTERVAL 30 DAY )
group by order_date) oc on o.order_date=oc.order_date
WHERE o.order_date BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
group by o.order_date
order by o.order_date;
order_date
orderAmount
customerAmount
2021-02-27
1
1
2021-03-01
3
1
2021-03-03
1
1
2021-03-04
1
0
View on DB Fiddle
Just count the first time a customer appears:
SELECT order_date, COUNT(*) as num_orders,
COUNT(DISTINCT customer_id) as distinct_customers_on_day,
SUM(SUM(seqnum = 1)) OVER (ORDER BY order_date) as running_distinct_customers
FROM (SELECT o.*,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) as seqnum
FROM orders o
WHERE o.order_date BETWEEN NOW() - INTERVAL 30 DAY AND NOW()
) o
GROUP BY order_date;
Here is a db<>fiddle.

Mysql query - month

I am a beginner in Mysql and I have a table like this:
create table purchase
(
purchase_ID INT primary key,
purchase_date DATE,
purchase_price INT
);
Insert into purchase values ('1', '2015-5-30', '10000');
Insert into purchase values ('2', '2016-7-30', '80000');
Insert into purchase values ('3', '2017-8-30', '50000');
Insert into purchase values ('4', '2016-10-30', '90000');
Now the question is: find which month has highest sales for the year 2016.
NOTE: consider purchase price as sales.
To find the answer for this, I tried this SQL statement:
SELECT
MAX(purchase_price) AS sales,
MONTH(purchase_date)
FROM
purchase
WHERE
CAST(purchase_date AS date) BETWEEN '2016-01-01' AND '2016-12-30'
and getting results as
sales month(purchase_date)
----------------------------
90000 7
but I am getting error in month because 10th month had highest sales not 7, can any one advise on this?
For using MAX, SUM, etc u need to do GROUP BY (aggregated query with GROUP BY)
SELECT MAX(purchase_price) as sales, MONTH(purchase_date) as month
from purchase where purchase_date between '2016-01-01' and '2016-12-30'
GROUP BY month
ORDER BY month desc
LIMIT 1
this query should work for you.
find which month has highest sales for the year 2016
SELECT *
FROM purchase
WHERE purchase_date BETWEEN '2016-01-01' AND '2016-12-30'
ORDER BY purchase_price DESC
LIMIT 1

SQL: Group by for last 3 months and last 5 months respectively

Based on a table of the sales from different time periods, I am trying to calculate aggregated values from 2 different time periods: (1) Sales where date > '2018-11-26' and (2) sales where date > '2018-09-26'
create table revenue (sales float, date_time datetime)
insert into revenue (sales,date_time) values (300, '2018-09-01')
insert into revenue (sales,date_time) values (200, '2018-10-01')
insert into revenue (sales,date_time) values (300, '2018-11-01')
insert into revenue (sales,date_time) values (400, '2019-01-01')
insert into revenue (sales,date_time) values (500, '2019-02-01')
I've seen other solutions that uses case when for time periods, however the difference in this case is that the time periods are not mutually exclusive.
The query I want should work something like this:
select sum(sales) from revenue
group by date_time where date_time > '2018-11-26',
date_time where date_time > '2018-09-26'
you can use union all
select 'p1' as prd , sum(sales) from revenue
where date_time >= '2018-11-26'
union all
select 'p2', sum(sales) from revenue
where date_time > '2018-09-26'
or you can use case when
select case when date_time >= '2018-11-26' then 'p1'
when date_time > '2018-09-26'
then 'p2' end as period, sum(sales) from revenue
group by case when date_time >= '2018-11-26' then 'p1'
when date_time > '2018-09-26'
then 'p2' end

SQL query for fetching every first event (by datetime field) in day of a month

I have table like events(id, date, event_name, user_id) and records like
(1, '2013-12-01 08:30:00', 'login', 9),
(2, '2013-12-01 08:33:00', 'login', 4),
(3, '2013-12-01 10:22:00', 'logout', 9),
(4, '2013-12-02 08:34:00', 'login', 9),
...
I need to fetch every first event for each (or specified) user in a day for every days in a month.
for ex:
2013-12-01 08:30:00, login, 9
2013-12-02 08:34:00, login, 0
...
Help me to construct properly SQL query
SELECT events.*
FROM
events INNER JOIN (SELECT user_id,
DATE(`date`) as day_event,
MIN(`date`) AS first_event
FROM events
GROUP BY
user_id,
DATE(`date`)) fe
ON events.user_id = fe.user_id
AND events.`date` = fe.first_event
Please see fiddle here.
If you only want to return a month, you can put your condition in your subquery:
(SELECT user_id,
DATE(`date`) as day_event,
MIN(`date`) AS first_event
FROM events
WHERE `date` >= '2013-12-01' AND `date` < '2014-01-01'
GROUP BY
user_id,
DATE(`date`)) fe
Try this---
SELECT *
FROM events
WHERE id IN (SELECT min(id)
FROM events
GROUP BY user_id, date)

Group by month including empty months

I want to select all my order values per month. I know this works fine with GROUP BY month but only with months with orders in it. Now I want also the months with no orders so I get all months.
This is my query:
SELECT SUM(VerkoopfactBedrag) AS bedrag, DATE_FORMAT(VerkoopfactDatum,'%M') AS date
FROM verkoopfacturen
WHERE Verkoopfact_UserId = 12
AND VerkoopfactDatum BETWEEN '2011-01-01' AND '2011-12-30'
GROUP BY MONTH(VerkoopfactDatum)
So when the result of a month is 0 I want to see the month with value 0 but now the month don't show up.
Is this possible?
One way to do this is to create and populate a table full of consecutive months.
You can then OUTER JOIN using that table.
So something like:
drop table if exists all_months;
create table all_months (a_month_id int unsigned PRIMARY KEY,a_month varchar(20) NOT NULL, UNIQUE KEY `all_months_uidx1` (a_month));
insert into all_months values (1,'January');
insert into all_months values (2,'February');
insert into all_months values (3,'March');
insert into all_months values (4,'April');
insert into all_months values (5,'May');
insert into all_months values (6,'June');
insert into all_months values (7,'July');
insert into all_months values (8,'August');
insert into all_months values (9,'September');
insert into all_months values (10,'October');
insert into all_months values (11,'November');
insert into all_months values (12,'December');
SELECT SUM(IFNULL(t1.VerkoopfactBedrag,0)) AS bedrag,
am.a_month AS date
from
(
select
ifnull(vn.VerkoopfactBedrag,0) as VerkoopfactBedrag,
cast(DATE_FORMAT(VerkoopfactDatum, '%M') as char) as mdate
FROM verkoopfacturen vn
WHERE Verkoopfact_UserId = 12
AND VerkoopfactDatum BETWEEN '2011-01-01' AND '2011-12-31'
GROUP BY DATE_FORMAT(VerkoopfactDatum, '%M')
) t1 RIGHT OUTER JOIN all_months am on t1.mdate = am.a_month
group by am.a_month
order by a_month_id asc;
PS Not sure if you have anything against Oudejaarsavond but there are 31 days in December ;-)
After searching for a simple solution i finally found this which I think is SIMPLE. This will show last year and this years sales side by side.
select
date_format(current_date - INTERVAL 1 YEAR,'%Y') as LAST_YR,
date_format(NOW(),'%Y') as THIS_YR,
monthname(date) as month,
sum(case when year(date) = date_format(current_date - INTERVAL 1 YEAR,'%Y') then amount else 0 end) as sales_ly,
sum(case when year(date) = DATE_FORMAT(NOW(),'%Y') then amount else 0 end) as sales_ty
from tablename
where date between date_format(current_date - INTERVAL 1 YEAR,'%Y-%01-%01')
and date_format(current_date, '%Y-%12-%31')
group by monthname(date)
order by max(month(date));