SELECT customer_email, count(*) AS Order_Count,
MAX(created_at) as Last_Order_Date,
SUM(base_total_paid) AS Total_Lifetime_Sales,
SUM(base_total_offline_refunded+base_total_online_refunded) AS Refund_Total,
FROM mage_sales_order AS o
WHERE o.created_at > “2018-01-01”
AND
value NOT IN (Select customer_email
FROM mage_sales_order
WHERE WHERE o.created_at < “2018-10-01”)
Trying to remove orders that have been purchased in the last week, however gets stuck on the WHERE AND, And not sure! Thank you for any help!
I think you want to remove email id who ordered < '2018-01-01' so it would be below query
SELECT customer_email, count(*) AS Order_Count,
MAX(created_at) as Last_Order_Date,
SUM(base_total_paid) AS Total_Lifetime_Sales,
SUM(base_total_offline_refunded+base_total_online_refunded) AS Refund_Total
FROM mage_sales_order AS o
WHERE o.created_at > '2018-01-01' AND
customer_email NOT IN (Select customer_email
FROM mage_sales_order
WHERE o.created_at < '2018-10-01'
)
group by customer_email
You need a group by. The answer to your question is:
SELECT customer_email, count(*) AS Order_Count,
MAX(created_at) as Last_Order_Date,
SUM(base_total_paid) AS Total_Lifetime_Sales,
SUM(base_total_offline_refunded+base_total_online_refunded) AS Refund_Total
FROM mage_sales_order AS o
WHERE o.created_at < CURRENT_DATE - INTERVAL '1 week'
GROUP BY customer_email;
If you want to filter customers who haven't made a recent order:
SELECT customer_email, count(*) AS Order_Count,
MAX(created_at) as Last_Order_Date,
SUM(base_total_paid) AS Total_Lifetime_Sales,
SUM(base_total_offline_refunded+base_total_online_refunded) AS Refund_Total
FROM mage_sales_order AS o
GROUP BY customer_email
HAVING MAX(o.created_at) < CURRENT_DATE - INTERVAL '1 week'
Note that date/time functions differ by database, so the exact syntax might differ depending on what database you are using.
Related
I'm working on a mysql request that make the sum of values by months including those with null values.
The request result send only the first line without making the sum operation.
SELECT SUM(IFNULL(t1.sub_total,0)) AS amount,
am.a_month AS date
FROM (
SELECT ifnull(vn.sub_total,0) as sub_total,
cast(DATE_FORMAT(order_date, '%M') as char) as mdate
FROM orders_new vn
WHERE order_status = 1
AND order_date BETWEEN '2022-01-01' AND '2022-12-31'
GROUP BY DATE_FORMAT(order_date, '%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;
result
below the source table
You don't need the GROUP BY clause in the subquery. Your query should be:
SELECT
SUM(IFNULL(t1.sub_total, 0)) AS amount,
am.a_month AS date
FROM
(SELECT
IFNULL(vn.sub_total, 0) AS sub_total,
CAST(DATE_FORMAT(order_date, '%M') AS char) AS mdate
FROM
orders_new vn
WHERE
order_status = 1
AND order_date BETWEEN '2022-01-01' AND '2022-12-31') t1
RIGHT OUTER JOIN
all_months am ON t1.mdate = am.a_month
GROUP BY
am.a_month
ORDER BY
a_month_id ASC;
I'm trying to reduce these queries to one so it's not three separate queries. Is there a better way to do this other than what I have? I'm also trying to sum all the totals together IE (invoiced_total + refund_total + credit_memo_total). The tables have no relation other than the customer, but I'm not looking to group by customer, just date. Any help would be much appreciated.
SELECT
SUM(qbi.amount) AS invoiced_total,
DATE_FORMAT(qbi.line_item_date, '%Y-%m-01') AS date
FROM
invoices as qbi
WHERE
qbi.`line_item_date` BETWEEN '2018-12-01' AND '2019-12-31'
GROUP BY
DATE_FORMAT(qbi.`line_item_date`, '%Y-%m-01')
ORDER BY
DATE_FORMAT(qbi.`line_item_date`, '%Y-%m-01');
SELECT
SUM(amount) AS refund_total,
DATE_FORMAT(refund_date, '%Y-%m-01') AS refund_date
FROM
refunds
WHERE
refund_date BETWEEN '2018-12-01' AND '2019-12-31'
GROUP BY
DATE_FORMAT(refund_date, '%Y-%m-01')
ORDER BY
DATE_FORMAT(refund_date, '%Y-%m-01');
SELECT
SUM(amount) AS credit_memo_total,
DATE_FORMAT(credit_memo_date, '%Y-%m-01') AS credit_memo_date
FROM
credit_memos
WHERE
credit_memo_date BETWEEN '2018-12-01' AND '2019-12-31'
GROUP BY
DATE_FORMAT(credit_memo_date, '%Y-%m-01')
ORDER BY
DATE_FORMAT(credit_memo_date, '%Y-%m-01');
If you want to join these queries you must also use a 4th query which will return all the distinct months from the 3 tables just in case there is a month missing in any of them.This is why you should use left joins for the tables:
SELECT d.date, i.invoiced_total, r.refund_total, c.credit_memo_total,
COALESCE(invoiced_total, 0) + COALESCE(refund_total, 0) + COALESCE(credit_memo_total, 0) AS total
FROM (
SELECT DATE_FORMAT(qbi.`line_item_date`, '%Y-%m-01') AS date FROM invoices UNION
SELECT DATE_FORMAT(refund_date, '%Y-%m-01') FROM refunds UNION
SELECT DATE_FORMAT(credit_memo_date, '%Y-%m-01') FROM credit_memos
) AS d
LEFT JOIN (
SELECT
SUM(qbi.amount) AS invoiced_total,
DATE_FORMAT(qbi.line_item_date, '%Y-%m-01') AS date
FROM
invoices as qbi
WHERE
qbi.`line_item_date` BETWEEN '2018-12-01' AND '2019-12-31'
GROUP BY
DATE_FORMAT(qbi.`line_item_date`, '%Y-%m-01')
) i ON i.date = d.date
LEFT JOIN (
SELECT
SUM(amount) AS refund_total,
DATE_FORMAT(refund_date, '%Y-%m-01') AS refund_date
FROM
refunds
WHERE
refund_date BETWEEN '2018-12-01' AND '2019-12-31'
GROUP BY
DATE_FORMAT(refund_date, '%Y-%m-01')
) r ON r.date = d.date
LEFT JOIN (
SELECT
SUM(amount) AS credit_memo_total,
DATE_FORMAT(credit_memo_date, '%Y-%m-01') AS credit_memo_date
FROM
credit_memos
WHERE
credit_memo_date BETWEEN '2018-12-01' AND '2019-12-31'
GROUP BY
DATE_FORMAT(credit_memo_date, '%Y-%m-01')
) c ON c.date = d.date
WHERE d.date BETWEEN '2018-12-01' AND '2019-12-31'
ORDER BY d.date
You would typically join the three queries. Assuming that all monthes are available in three tables, you could do:
SELECT
i.invoice_month my_month,
i.invoiced_total,
r.refund_total,
c.credit_total,
i.invoiced_total + r.refund_total + c.credit_total amount_total
FROM (
SELECT
SUM(amount) AS invoiced_total,
DATE_FORMAT(line_item_date, '%Y-%m-01') AS invoice_month
FROM invoices
WHERE line_item_date BETWEEN '2018-12-01' AND '2019-12-31'
GROUP BY invoice_month
) i
INNER JOIN (
SELECT
SUM(amount) AS refund_total,
DATE_FORMAT(refund_date, '%Y-%m-01') AS refund_month
FROM refunds
WHERE refund_date BETWEEN '2018-12-01' AND '2019-12-31'
GROUP BY refund_month
) r
INNER JOIN (
SELECT
SUM(amount) AS credit_total,
DATE_FORMAT(credit_memo_date, '%Y-%m-01') AS credit_month
FROM credit_memos
WHERE credit_memo_date BETWEEN '2018-12-01' AND '2019-12-31'
GROUP BY credit_memo_month
) c
ORDER BY i.invoice_month
Side note: in MySQL you can use column aliases in the GROUP BY clause (and in the ORDER BY clause): this helps shortening the query.
I'm know this can be written as a single SQL statement, but I just don't know how to do it. I have two separate queries. Ont that pulls all orders from a specific period of last year
SELECT * FROM `order` WHERE date_added BETWEEN '2014-10-01' AND '2014-11-01';
and one that pulls from the last month
SELECT * FROM `order` WHERE date_added BETWEEN DATE_SUB( now(), INTERVAL 1 MONTH) AND Now() ORDER BY date_added ASC
What I want to do is now join the two so that I only get the customer_id of orders that were placed inside of the date range last year (query 1), but haven't placed an order in the last month (query 2).
I know there is a way to set this up as a join, but my knowledge on sql join's is not very limited. Thanks for any help.
http://sqlfiddle.com/#!9/35ed0/1
SELECT * FROM `order`
WHERE date_added BETWEEN '2014-10-01' AND '2014-11-01'
AND customer_id NOT IN (
SELECT DISTINCT customer_id FROM `order`
WHERE date_added BETWEEN DATE_SUB( now(), INTERVAL 1 MONTH) AND Now())
UPDATE If you need only 1 records per customer_id, here is an example . It is not very best from performance perspective. But it returns only last (according to the date_added column) order per customer.
SELECT t.*,
if(#fltr=customer_id, 0, 1) fltr,
#fltr:=customer_id
FROM (SELECT *
FROM `order`
WHERE date_added BETWEEN '2014-10-01' AND '2014-11-01'
AND customer_id NOT IN (
SELECT DISTINCT customer_id FROM `order`
WHERE date_added BETWEEN DATE_SUB( now(), INTERVAL 1 MONTH) AND Now())
ORDER BY customer_id, date_added DESC
) t
HAVING (fltr=1);
I usually use a correlated not exists predicate for this as I feel that it corresponds well with the intent of the question:
SELECT *
FROM `order` o1
WHERE date_added BETWEEN '2014-10-01' AND '2014-11-01'
AND NOT EXISTS (
SELECT 1
FROM `order` o2
WHERE date_added BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()
AND o1.customer_id = o2.customer_id
);
I like to approach these questions using group by and having. You are looking for customer ids, so:
select o.customer_id
from orders o
group by o.customer_id
having sum(date_added BETWEEN '2014-10-01' AND '2014-11-01') > 0 and
sum(date_added BETWEEN DATE_SUB( now(), INTERVAL 1 MONTH) AND Now()) = 0;
SELECT DISTINCT d.customer_id, d.date_added FROM `order` d
WHERE d.customer_id NOT IN (
SELECT DISTINCT i.customer_id
FROM `order` i
WHERE i.date_added > '2015-02-15 14:00:00'
)
ORDER BY d.date_added DESC;
The above query should return customer_id of customers who have not ordered after 15 Feb 2015 (I think). But very first record is
17168, 2015-08-16 17:36:00
What am I doing wrong?
This below query
SELECT DISTINCT i.customer_id,i.date_added FROM `order` i
WHERE i.date_added > '2015-02-15 14:00:00'
ORDER BY i.date_added ASC;
returns expected result i.e. list of customer ids for orders placed after 15 Feb
P.S. customer_id can not be NULL
Can customer_id or data_added be NULL? Try
SELECT DISTINCT d.customer_id,d.date_added
FROM order d
WHERE d.customer_id NOT IN
(SELECT DISTINCT i.customer_id FROM order i
WHERE i.date_added > '2015-02-15 14:00:00'
and customer_id IS NOT NULL
and i.date_added IS NOT NULL)
ORDER BY d.date_added DESC;
Edit
The way you wrote your query will get you customer_ids with an order before '2015-02-15 14:00:00'. But if the customer ordered something after this date they might be in the resultset.
Edit2
Why not write
SELECT DISTINCT customer_id, date_added
FROM order
WHERE date_added <= '2015-02-15 14:00:00'
ORDER BY date_added DESC;
I would use a correlated not exists query to exclude all customers that have any order after the specified date:
SELECT o1.customer_id, o1.date_added
FROM `order` o1
WHERE NOT EXISTS (
SELECT 1
FROM `order` o2
WHERE date_added > '2015-02-15 14:00:00'
AND o1.customer_id = o2.customer_id
)
ORDER BY o1.date_added DESC;
If you want customers who have not ordered since a certain date, I would just use group by and having:
SELECT o.customer_id, MAX(o.date_added) as most_recent
FROM `order` o
GROUP BY o.customer_id
HAVING MAX(o.date_added) <= '2015-02-15 14:00:00';
I have read almost 10+ questions related to mine but no one worked in my case. As i have 3 tables in my DB and i am trying to calculate sale from them with respect to time (Yearly sale). where i need to GROUP BY my query by date_added. In MYSQL it worked fine and give me fine result but in redshift i am stuck.
MYSQL QUERY:
SELECT
MONTHNAME(o.date_added) AS MONTH,
YEAR(o.date_added) AS YEAR,
COUNT(o.order_id) AS orders,
FROM
order o
LEFT JOIN(
SELECT
op.order_id,
SUM(op.quantity) AS op_qty,
SUM(op.total) AS total,
SUM(op.cost) AS cost
FROM
order_product op
GROUP BY
op.order_id
) op
ON
op.order_id = o.order_id
LEFT JOIN(
SELECT
order_id,
SUM(IF(CODE = 'coupon', VALUE, 0)) AS coupon
FROM
order_total
WHERE
1
GROUP BY
order_id
) ot
ON
ot.order_id = o.order_id
WHERE
(
DATE(o.date_added) >= DATE_ADD(NOW(), INTERVAL - 24 MONTH) AND DATE(o.date_added) <=
DATE(NOW())) AND(o.order_status_id = '22' OR o.order_status_id = '23')
GROUP BY
MONTH(o.date_added),
YEAR(o.date_added)
ORDER BY
date_added ASC
LIMIT 0, 25
This MYSQL query working very fine but when i convert it to RedShift's POSTGRE format it gives me error of Invalid operation: column "o.date_added" must appear in the GROUP BY clause or be used in an aggregate function;
POSTGRES Query:
SELECT
EXTRACT(MONTH FROM o.date_added) AS month,
EXTRACT(YEAR FROM o.date_added) AS year,
COUNT(o.order_id) AS orders
FROM
orders o
LEFT JOIN
(
SELECT
op.order_id,
SUM(op.quantity) AS op_qty,
SUM(op.total) AS total,
SUM(op.cost) AS cost
FROM
order_product op
GROUP BY
op.order_id
) op
ON op.order_id = o.order_id
LEFT JOIN
(
SELECT
order_id,
SUM(CASE
WHEN CODE = 'coupon' THEN VALUE
ELSE 0
END) AS coupon
FROM
order_total
WHERE
1
GROUP BY
order_id
) ot
ON ot.order_id = o.order_id
WHERE
(
DATE(o.date_added) >= now() + interval '-24 month'
AND DATE(o.date_added) <= DATE(NOW())
)
AND (
o.order_status_id = '22'
OR o.order_status_id = '23'
)
GROUP BY
(EXTRACT(MONTH FROM o.date_added), EXTRACT(YEAR FROM o.date_added))
ORDER BY
o.date_added ASC LIMIT 25
Is there any syntax error in postgre query and also why i need to add o.date_added in GROUP BY
Your ORDER BY clause has o.date_added in it but your actual result set does not have it. The ORDER BY is done after the query is done.
You can use:
ORDER BY month asc, year asc LIMIT 25
Also, you can remove the extra parentheses from the GROUP BY:
GROUP BY EXTRACT(MONTH FROM o.date_added), EXTRACT(YEAR FROM o.date_added)
DB-Fiddle
See Redshift documentation for use of now() function. Use getdate() instead, as the now() seems to be deprecated.
A column in an ORDER BY clause in a query containing GROUP BY works as if it were mentioned in the SELECT clause.
You have
SELECT
MONTHNAME(o.date_added) AS MONTH,
YEAR(o.date_added) AS YEAR,
COUNT(o.order_id) AS orders,
FROM
order o
...
GROUP BY
MONTH(o.date_added),
YEAR(o.date_added)
ORDER BY
date_added ASC
LIMIT 0, 25
In MySQL this takes advantage of its notorious nonstandard handling of GROUP BY (read this. https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html)
What you want, to get a query that works in multiple DBMSs, is this instead.
ORDER BY
MONTH(o.date_added) ASC,
YEAR(o.date_added) ASC
Adding o.date_added to your GROUP BY clause is incorrect, because you are grouping not by the entire date, but by the month and year of the date.
I found the ERROR.I used SQL Workbench and get the Error about NOW() function that i was using in my POSTGRE query.
Simply, i juts replaced NOW() with CURRENT_DATE and things worked for me. Also, i get Error for LIMIT 0, 25 but in POSTGRE , they allow LIMIT 25 [OFFSET n] .
Now my query looks like:
SELECT
EXTRACT(MONTH FROM o.date_added) AS month,
EXTRACT(YEAR FROM o.date_added) AS year,
COUNT(o.order_id) AS orders
FROM
orders o
LEFT JOIN
(
SELECT
op.order_id,
SUM(op.quantity) AS op_qty,
SUM(op.total) AS total,
SUM(op.cost) AS cost
FROM
order_product op
GROUP BY
op.order_id
) op
ON op.order_id = o.order_id
LEFT JOIN
(
SELECT
order_id
FROM
order_total
WHERE
1
GROUP BY
order_id
) ot
ON ot.order_id = o.order_id
WHERE
(
DATE(o.date_added) >= CURRENT_DATE + interval '-24 month'
AND DATE(o.date_added) <= DATE(CURRENT_DATE)
)
GROUP BY EXTRACT(MONTH FROM o.date_added), EXTRACT(YEAR FROM o.date_added)
ORDER BY year ASC, month ASC LIMIT 25
NOTE: IF YOU ARE WORKING ON REDSHIFT. IT DO NOT BERIEF ABOUT ERROR. I RECOMMEND TO USE SQL WORKBENCH. IT EXPLAIN ABOUT ERROR.