need to get data from multiple mySQL tables grouping by date - mysql

I have 2 tables
1st: order
columns: id, date, price
2nd: paypal
columns: id, posted_date, amount
the columns date and posted_date contains the full date & time details; day/month/year hrs:minute:seconds
I need to get the data by grouping by the day from the both tables
order.date (day by day)
count all orders from order table for each day
sum of all price records from order table for each day
sum of all amount records from the another table paypal table for the same days
I can't imagine if I should use join, union, union all, or just merge by comma

SELECT DATE(O.`dater`) AS Dates,
COUNT(O.orders) AS Order_count,
SUM(O.price) as Total_Price,
(SELECT SUM(amount) FROM paypal WHERE DATE(O.`dater`)=`posted_date`) AS Total_Amount
FROM orders O
GROUP BY DATE(O.`dater`)
Note:(I have used column dater instead of column date)
Hope this helps.

This one working for me :)
SELECT DATE(O.`date`) AS Dates,
COUNT(O.order) AS Order_count,
SUM(O.price) as Total_Price,
(SELECT SUM(amount) FROM paypal WHERE DATE(O.`date`)=`posted_date`) AS Total_Amount
FROM order O
GROUP BY DATE(O.`date`)

Related

SQL Consecutive Monthly Purchases

I'm having great difficulty writing this query and cannot find any answers online which could be applied to my problem.
I have a couple of tables which looks similar to the below with. Each purchase date corresponds with an item purchased.
Cust_ID
Purchase_Date
123
08/01/2022
123
08/20/2022
123
09/05/2022
123
10/08/2022
123
12/25/2022
123
01/26/2023
The result I am looking for should contain the customers ID, a range of the purchases, the number of consecutive months they had made a purchase (regardless of which day they purchased), and a count of how many purchases they had made in the time frame. The result should look something like the below for my example.
Cust_ID
Min Purchase Date
Max Purchase Date
Consecutive Months
No. Items Purchased
123
08/01/2022
10/08/2022
3
4
123
12/25/2022
01/26/2023
2
2
I have tried using CTEs with querys similar to
WITH CTE as
(
SELECT
PaymentDate PD,
CustomerID CustID,
DATEADD(m, -ROW_NUMBER() OVER (PARTITION BY c.CustomerID ORDER BY
DATEPART(m,PaymentDate)), PaymentDate) as TempCol1,
FROM customers as c
LEFT JOIN payments as p on c.customerid = p.customerid
GROUP BY c.CustomerID, p.PaymentDate
)
SELECT
CustID,
MIN(PD) AS MinPaymentDate,
MAX(PD) AS MaxPaymentDate,
COUNT(*) as ConsecutiveMonths,
FROM CTE
GROUP BY CustID, TempCol1
However, the above failed to properly count consecutive months. When the payment dates matched a month apart (e.g. 1/1/22 - 2/1/22), the query properly counts the consecutive months. However, if the dates do not match from month to month (e.g. 1/5/22 - 2/15/22), the count breaks.
Any guidance/help would be much appreciated!
This is just a small enhancement on the answer already given by ahmed. If your date range for this query is more than a year, then year(M.Purchase_Date) + month(M.Purchase_Date) will be 2024 for both 2022-02-01 and 2023-01-01 as YEAR() and MONTH() both return integer values. This will return incorrect count of consecutive months. You can change this to use CONCAT() or FORMAT(). Also, the COUNT(*) for ItemsPurchased should be counting the right hand side of the join, as it is a LEFT JOIN.
WITH consecutive_months AS
(
SELECT *,
DATEADD(
month,
-DENSE_RANK() OVER (
PARTITION BY CustomerID
ORDER BY YEAR(PaymentDate), MONTH(PaymentDate)
),
PaymentDate
) AS grp_date
FROM payments
)
SELECT
C.CustomerID AS CustID,
MIN(M.PaymentDate) AS MinPaymentDate,
MAX(M.PaymentDate) AS MaxPaymentDate,
COUNT(DISTINCT FORMAT(M.PaymentDate, 'yyyyMM')) AS ConsecutiveMonths,
COUNT(M.CustomerID) AS ItemsPurchased
FROM customers C
LEFT JOIN consecutive_months M
ON C.CustomerID = M.CustomerID
GROUP BY C.CustomerID, YEAR(M.grp_date), MONTH(M.grp_date)
Here's a db<>fiddle
You need to use the dense_rank function instead of the row_number, this will give the same rank for the same months and avoid breaking the grouping column. Also, you need to aggregate for 'year-month' of the grouping date column.
with consecutive_months as
(
select *,
Purchase_Date - interval
dense_rank() over (partition by Cust_ID order by year(Purchase_Date), month(Purchase_Date))
month as grp_date
from payments
)
select C.Cust_ID,
min(M.Purchase_Date) as MinPurchaseDate,
max(M.Purchase_Date) as MaxPurchaseDate,
count(distinct year(M.Purchase_Date), month(M.Purchase_Date)) as ConsecutiveMonthsNo,
count(M.Cust_ID) as ItemsPurchased
from customers C left join consecutive_months M
on C.Cust_ID = M.Cust_ID
group by C.Cust_ID, year(M.grp_date), month(M.grp_date)
See demo on MySQL
You tagged your question with MySQL, while it seems that you posted an SQL Server query syntax, for SQL Server just use dateadd(month, -dense_rank() over (partition by Cust_ID order by year(Purchase_Date), month(Purchase_Date)), Purchase_Date).
See demo on SQL Server.

SQL Moving window over two level of groupby

I have the following table of orders for users like the following:
CREATE TABLE orders (
order_id UUID,
user_id UUID,
date date,
order_type integer
);
I want to write SQL to do the following:
For every order want to compute the number of orders the user has within a previous week (7 days).
Write the following, but it counts the number of orders for each user but not for two levels of groupby.
SELECT order_id, user_id,
COUNT(order_id) OVER(PARTITION BY user_id ORDER BY date ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) as num_orders_7days
FROM orders
You should use RANGE clause instead of ROWS with the proper date intervals:
SELECT order_id, user_id, date,
COUNT(order_id) OVER (
PARTITION BY user_id
ORDER BY date
RANGE BETWEEN INTERVAL 7 day PRECEDING AND INTERVAL 1 day PRECEDING
) as num_orders_7days
FROM orders;
See the demo.

how can i make query with couple of profits?

first ,i need to get the sum of TotalPrice of sport's and music's departments from the first 3 months of 2016,second, i need to get the result of what i wrote before dividing to sum of all TotalPrice at the year of 2016 from all departments, and third- i need to get the first result dividing to sum of all Total price from all over the years.
all this at the same query!
thanks!
the table called Sales and the attributes are: S_id, date, department, totalPrice.
THIS IS MY CHRY :
Select sum(TotalPrice) as sportMusic, sportMusic/sum(TotalPrice)
From Sales
Where (Department="MUSIC" OR Department="SPORT") and
DATE BETWEEN "2016/01/01" AND "2016/03/31"
You can use your query and two more queries as subqueries (also called "derived tables") in your from clause. Cross join the three result rows and use the totals in your select clause. Something along the lines of:
select
ms_2016_q1.total as ms_2016_q1_total,
ms_2016_q1.total / all_2016.total as rate_2016,
ms_2016_q1.total / all_years.total as rate_all
from
(
select sum(totalprice) as total
from sales
where department in ('MUSIC', 'SPORT')
and date between date '2016-01-01' and date '2016-03-31'
) ms_2016_q1
cross join
(
select sum(totalprice) as total
from sales
where date between date '2016-01-01' and date '2016-12-31'
) all_2016
cross join
(
select sum(totalprice) as total
from sales
) all_years;

Select from 2 tables only the new entries in table 2

I got 2 tables, Customers and Payment. I'm trying to select only the new customers that have payments in the specified month and year, and no previous payments in another month.
table Customer
id - name
table Payment
id - id_customer - month - year - amount
SELECT * FROM customer, payment
WHERE Customer.id = Payment.id_customer
AND month = '$month'
AND year = '$year'
That gets me all the payments in a specific month and year, but I don't know how to exclude all the customers that had other previous payments.
Thank you for your time.
I don't think that you could achieve this without a third table. What you can do is create a third table with all the ids that you have selected in query and update it every time you run a select query.
Then the below query might work:
SELECT * FROM customer c, payment p WHERE c.id = p.id_customer
AND month = '$month'AND year = '$year'AND p.id NOT IN (SELECT id FROM
third_table)
Hope it answers your question.
To get the first date of payment, use GROUP BY. But, you will have to convert the value to something like a date first:
SELECT p.id_customer, MIN(CONCAT_WS, '-', p.year, p.month)) as first_yyyymm
FROM payment p
GROUP BY p.id_customer;
You should store the payment date as a date.

Selecting customers who have spent more than a certain amount in a date range

I have a sales table which has one row for each sales tranaction. This table has date of sale and customer id as well.
I am looking for a way to select all those customers who have total spending in the specified range with in a specified date range. For example, get all customers who spent between 100 and 1000, between 2016-07-01 and 2016-08-15. This then has to become part of a larger query.
This query
select
customer_id,
sum(sale_amount)
from
sales_receipt
where
DATE(sales_receipt.sale_date) BETWEEN '2016-07-01' AND '2016-08-29'
group by
customer_id;
gives me all customers and their total spending in the specified date range but I need only those customers for whom sum(sale_amount) is between 100 and 1000.
Can any one help.
Try to use
select customer_id, sum(sale_amount) from sales_receipt where
DATE(sales_receipt.sale_date) BETWEEN '2016-07-01' AND '2016-08-29'
group by customer_id having sum(sale_amount)>=100 and sum(sale_amount)<=100
You'd use the HAVING clause here because you want to filter on the aggregated result:
SELECT
customer_id,
SUM(sale_amount) AS total_amount
FROM sales_receipt
WHERE DATE(sales_receipt.sale_date) BETWEEN '2016-07-01' AND '2016-08-29'
HAVING total_amount BETWEEN 100 AND 1000
GROUP BY customer_id;