I need help to select daily payments made and group by the organization and date.
Group by date, then the total number of payments and the sum total amount of payments for each day
Tables are as follows,
organizations
-----------------------------
| id | name |
+-------------+-------------+
| 1 | org_1 |
+-------------+-------------+
| 2 | org_2 |
+-------------+-------------+
| 3 | org_2 |
-----------------------------
payments
------------------------------------------------------------
| id | org_id | amount | date_created |
+-----------+------------+-------------+-------------------+
| 1 | 2 | 20 | 2020-11-06 |
+-----------+------------+-------------+-------------------+
| 2 | 2 | 10 | 2020-11-06 |
+-----------+------------+-------------+-------------------+
| 3 | 1 | 50 | 2020-11-05 |
+-----------+------------+-------------+-------------------+
| 4 | 2 | 10 | 2020-11-05 |
------------------------------------------------------------
Expected Result
----------------------------------------------------------------------------------------------
| date_created | total_amount | num_payments | org_1 | org_2 | org_3 |
+----------------+----------------+-------------------+-----------+-------------+------------+
| 2020-11-06 | 30.00 | 2 | 0 | 2 | 0 |
+----------------+----------------+-------------------+-----------+-------------+------------+
| 2020-11-05 | 60.00 | 2 | 1 | 1 | 0 |
+----------------+----------------+-------------------+-----------+-------------+------------+
Use conditional aggregation:
select p.date_created,
sum(p.amount) as total_amount,
count(*) as num_payments,
sum(case when o.name = 'org_1' then p.amount else 0 end) as org_1,
sum(case when o.name = 'org_2' then p.amount else 0 end) as org_2,
sum(case when o.name = 'org_3' then p.amount else 0 end) as org_3
from payments p
inner join organizations o on o.id = p.org_id
group by p.date_created
Related
I want to get count of different statuses for bookings for each event and some other data. Each row should represent an event.
So I have an events table and a bookings table.
Events table has id, name, max_allowed
Bookings table has id,event_id,status
Status can be booked, canceled, waitlisted.
I want to get data for all events with the count for each status.
So I need these columns -
event_id
booked_count
canceled_count
waitlisted_count
remaining_slots - (max_allowed - booked_count)
occupancy_rate - booked_count/max_allowed
Sample data:
Events
| id | name | max_allowed |
|---- |--------- |------------- |
| 1 | Yoga | 5 |
| 2 | Boxing | 2 |
| 3 | Pilates | 5 |
Bookings
| id | event_id | status |
|---- |---------- |------------ |
| 1 | 1 | booked |
| 2 | 1 | booked |
| 3 | 2 | booked |
| 4 | 2 | canceled |
| 5 | 2 | booked |
| 6 | 2 | waitlisted |
| 7 | 3 | booked |
| 8 | 3 | booked |
| 9 | 3 | booked |
Output:
| event_id | booked_count | canceled_count | waitlisted_count | remaining_slots | occupancy_rate |
|---------- |-------------- |---------------- |------------------ |----------------- |---------------- |
| 1 | 2 | 0 | 0 | 3 | 0.4 |
| 2 | 2 | 1 | 1 | 0 | 1 |
| 3 | 3 | 0 | 0 | 2 | 0.6 |
Use conditional aggregation:
select t.*,
greatest(0, t.max_allowed - t.booked_count + t.canceled_count - t.waitlisted_count) remaining_slots,
least(t.max_allowed, t.booked_count - t.canceled_count + t.waitlisted_count) / t.max_allowed occupancy_rate
from (
select e.id, e.name, e.max_allowed,
sum(status = 'booked') booked_count,
sum(status = 'canceled') canceled_count,
sum(status = 'waitlisted') waitlisted_count
from Events e left join Bookings b
on b.event_id = e.id
group by e.id, e.name, e.max_allowed
) t
Try below query.
with src_data as
(select
event_id,
sum(case when status='booked' then 1 else 0 end ) as booked_count,
sum(case when status='canceled' then 1 else 0 end ) as canceled_count,
sum(case when status='waitlisted' then 1 else 0 end ) as waitlisted_count
from bookings group by event_id
)
select
s.event_id,
s.booked_count,
s.canceled_count,
s.waitlisted_count,
e.max_allowed-s.booked_count,
s.booked_count/e.max_allowed
from events e inner join src_data s
on e.id=s.event_id;
Don't know how to excatly name the problem. Therefore my example tables:
People:
id_people | peopleName |
------------------------
1 | John |
2 | Jane |
3 | Frank |
4 | Emma |
Courses:
id | id_course | id_people | date |
-----------------------------------------
1 | 1 | 1 | 2011-02-14 |
2 | 2 | 1 | 2013-05-01 |
3 | 3 | 1 | 2015-08-25 |
4 | 1 | 2 | 2012-01-05 |
5 | 1 | 4 | 2017-10-10 |
Now I want to generate a table where I have one row per person and for every course a column with the date like:
id_people | peopleName | Course1 | Course2 | Course3 |
---------------------------------------------------------------
1 | John | 2011-02-14 | 2013-05-01 | 2015-08-25 |
2 | Jane | 2012-01-05 | | |
3 | Frank | | | |
4 | Emma | 2017-10-10 | | |
I tried following query:
SELECT *,
max(case when courses.id_course = 1 then cource.date end) as Course1,
max(case when courses.id_course = 2 then cource.date end) as Course2,
max(case when courses.id_course = 3 then cource.date end) as Course3
FROM people
JOIN courses ON people.id_people = courses.id_people
GROUP BY people.id_people
But I got the error #1055 ([..] this is incompatible with sql_mode=only_full_group_by).
So, it forces me to add the column course.id, course.id_course and course.date to the group by statemant. This results in a row per per people and course.
How can I get my desired resulting table with a sql statment?
I do not have the privilege to change the sql_mode variable.
So it forces me to add the column course.id, course.id_course and
course.date to the group by statemant...
No it does not.
You only need to change the join to a LEFT JOIN and group by people.id_people, people.peopleName and you will get the results that you want:
SELECT people.id_people, people.peopleName,
max(case when courses.id_course = 1 then courses.date end) as Course1,
max(case when courses.id_course = 2 then courses.date end) as Course2,
max(case when courses.id_course = 3 then courses.date end) as Course3
FROM people
LEFT JOIN courses ON people.id_people = courses.id_people
GROUP BY people.id_people, people.peopleName
See the demo.
Results:
| id_people | peopleName | Course1 | Course2 | Course3 |
| --------- | ---------- | ----------- | ----------- | ----------- |
| 1 | John | 2011-02-14 | 2013-05-01 | 2015-08-25 |
| 2 | Jane | 2012-01-05 | | |
| 3 | Frank | | | |
| 4 | Emma | 2017-10-10 | | |
You haven't define id_people to be a primary key or at least unique. You should probably do that.
In the meantime, you can aggregate first and then join:
SELECT *
FROM people p JOIN
(SELECT c.id_people
max(case when c.id_course = 1 then c.date end) as Course1,
max(case when c.id_course = 2 then c.date end) as Course2,
max(case when c.id_course = 3 then c.date end) as Course3
FROM courses c
GROUP BY c.id_people
) c
USING (id_people);
I have two table one is order_details and second is orders.
1) order_details
id | order_id | item | order_units | is_cancelled |
------------------------------------------------------------------
1 | 00001 | Mobile | 2 | 0 |
2 | 00001 | Headphone | 2 | 0 |
3 | 00001 | cover | 5 | 0 |
4 | 00002 | charger | 1 | 0 |
5 | 00002 | mobile | 1 | 0 |
6 | 00004 | Tablet | 2 | 0 |
7 | 00005 | Mobile | 1 | 0 |
8 | 00005 | Battery | 2 | 1 |
9 | 00006 | Mobile | 1 | 0 |
10 | 00006 | speaker | 1 | 0 |
11 | 00006 | Motinor | 1 | 0 |
12 | 00007 | Laptop | 2 | 0 |
2) orders
order_id | date | time |total_amount| round |discount|refund
-----------------------------------------------------------------------
00001 | 2017-06-16 |10:10:45 | 456.12 |-0.12 | 0 | 0
00002 | 2017-06-16 |10:25:45 | 600.00 | 0.00 | 10 | 50
00004 | 2017-06-16 |11:10:45 | 300.55 |-0.05 | 0 | 0
00005 | 2017-06-16 |12:10:45 | 200.45 | 0.05 | 20 | 0
00006 | 2017-06-16 |12:40:45 | 685.00 | 0.00 | 50 | 0
00007 | 2017-06-24 |14:10:45 | 888.35 | 0.15 | 0 | 0
I want to join the "order_details" with "orders" and the result should be as below:
---------------------------------------------------------------------
date | time | hour |order_count| total_units| net_amount
---------------------------------------------------------------------
| 2017-06-16 |10:10:45 | 10 | 2 | 11 | 996
| 2017-06-16 |11:10:45 | 11 | 1 | 2 | 300.50
| 2017-06-16 |12:40:45 | 12 | 2 | 4 | 180.50
--------------------------------------------------------------------
I have created a sql query for the above result format and all columns outputs are correct except the "total_units", its showing null.
The following query i have used:
SELECT hdr.date,hdr.time, LPAD(HOUR(hdr.time),2,'0') AS hour, COUNT(hdr.`order_id`) AS order_count, dtl.total_units, SUM((hdr.total_amount+hdr.round-hdr.discount)-hdr.refund) AS net_amount
FROM orders hdr
LEFT JOIN (
SELECT order_id, SUM(qty) AS total_units
FROM order_details
WHERE is_cancelled=0) dtl ON dtl.order_id = hdr.order_id
WHERE DATE(hdr.date) = '2017-06-16 ' AND (HOUR(hdr.time) BETWEEN ('10') AND ('12'))
GROUP BY hdr.date, HOUR(hdr.time)
Please help me to correct this query and generate the exact output as above.
Sorry, One correction in my query..
SELECT hdr.date,hdr.time, LPAD(HOUR(hdr.time),2,'0') AS hour, COUNT(hdr.`order_id`) AS order_count, dtl.total_units, SUM((hdr.total_amount+hdr.round-hdr.discount)-hdr.refund) AS net_amount
FROM orders hdr
LEFT JOIN (
SELECT order_id, SUM(order_units) AS total_units
FROM order_details
WHERE is_cancelled=0) dtl ON dtl.order_id = hdr.order_id
WHERE DATE(hdr.date) = '2017-06-16 ' AND (HOUR(hdr.time) BETWEEN ('10') AND ('12'))
GROUP BY hdr.date, HOUR(hdr.time)
I have made some corrections in the query and it is working fine now:
SELECT hdr.date,hdr.time, LPAD(HOUR(hdr.time),2,'0') AS hour, COUNT(hdr.`order_id`) AS order_count, SUM(dtl.order_units) AS total_units, SUM((hdr.total_amount+hdr.round-hdr.discount)-hdr.refund) AS net_amount
FROM orders hdr
LEFT JOIN (
SELECT order_id, SUM(order_units) AS order_units
FROM order_details
WHERE is_cancelled=0 GROUP BY order_id) dtl ON dtl.order_id = hdr.order_id
WHERE DATE(hdr.date) = '2017-06-16 ' AND (HOUR(hdr.time) BETWEEN ('10') AND ('12'))
GROUP BY hdr.date, HOUR(hdr.time)
Thank you.
Consider following table:
+------------+-----------+-------------+---------+------------+--------+-------------+
| client_id | TradeDate | servicetype | SEGMENT | OrdChannel | orders | OrderAmount |
+------------+-----------+-------------+---------+------------+--------+-------------+
| 1 | 20140611 | Type_1 | CASH | TT | 1 | 39275 |
| 2 | 20150119 | Type_1 | CASH | DNT | 2 | 11856.9 |
| 3 | 20150922 | Type_1 | FNO | OTHER | 1 | 854750 |
| 4 | 20151223 | Type_1 | CASH | TT | 5 | 71075 |
| 5 | 20140529 | Type_1 | Offline | FNO | 1 | 0 |
| 6 | 20160310 | Type_2 | CASH | WEB | 2 | 8009.6 |
| 7 | 20150318 | Type_1 | Offline | FNO | 2 | 432900 |
| 8 | 20150914 | Type_2 | CASH | WEB | 2 | 15612 |
| 9 | 20160317 | Type_2 | FNO | MINI | 1 | 9000 |
| 10 | 20140421 | Type_1 | CASH | TT | 8 | 17112.5 |
+------------+-----------+-------------+---------+------------+--------+-------------+
I am trying to group this data by client_id and TradeDate. Thus final dataset would contain each row for every <client-id, TradeDate> pair.
I want to compute following features from this data:
For each type of SEGMENT in every pair, I want to compute sum of orders and OrderAmount
Similarly, for each type of OrdChannel in every pair, I want to compute sum of orders and OrderAmount
Finally, a count of each servicetype i.e. Type_1 and Type_2.
Thus final dataset would contain columns similar to shown below:
+------------+-----------+-------------+---------+------------+--------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| client_id | TradeDate | SEGMENT_CASH_orders_sum | SEGMENT_CASH_OrderAmount_sum.... | OrdChannel_TT_orders_sum | OrdChannel_TT_OrderAmount_sum.... | servicetype_Type_1_count | servicetype_Type_2_count |
+------------+-----------+-------------+---------+------------+--------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
So far, I have tried:
select clientsrno, TradeDate, SEGMENT, COUNT(orders) from orders group by clientsrno, TradeDate, SEGMENT;
but it's not giving separate columns for SEGMENT_CASH-orders_sum, etc.
Instead the output I am getting is:
+------------+-----------+---------+---------------+
| clientsrno | TradeDate | SEGMENT | COUNT(orders) |
+------------+-----------+---------+---------------+
| 44 | 20141209 | CASH | 23 |
| 44 | 20141211 | FNO | 10 |
+------------+-----------+---------+---------------+
You can do with a lot of sum( CASE .... END)
this is a suggestionfor the firts column
select client_di, TradeDate
sum (case SEGMENT
when 'CASH' then orders ELSE 0 END) as SEGMENT_CASH_orders_sum,
sum (case SEGMENT
when 'CASH' then OrderAmount ELSE 0 END) as SEGMENT_CASH_ordersAmount_sum,
sum (case SEGMENT
when 'FNO' then orders ELSE 0 END) as SEGMENT_FNO_orders,
sum (case SEGMENT
when 'FNO' then OrderAmount ELSE 0 END) as SEGMENT_FNO_ordersAmount_sum
from my_table
group by client_id, TradeDate
You can do for example:
SELECT clientsrno, TradeDate, SEGMENT, COUNT(orders), sumOrders.total FROM tabletest
INNER JOIN (
SELECT tabletest.tradeDate, SUM(orders) as total FROM tabletest
GROUP BY clientsrno, TradeDate, SEGMENT
) sumOrders ON tableTest.tradeDate = sumOrders.tradeDate
GROUP BY clientsrno, TradeDate, SEGMENT
And repeat the process for every sum you need.
I need help generating SQL for MySQL database.
I have three tables:
Organisations
Members
Payments
Organisations table:
+------------+---------+--------+
| id | name |website |
+------------+---------+--------+
| 1 | AAA | a.com |
|-------------------------------+
| 2 | BBB | b.com |
+------------+---------+--------+
Members table:
+------------+-------------------+--------+-----------------+-----------+
| id | organisation_id |name | Payment_confirm | join_date |
+------------+-------------------+--------+-----------------+-----------+
| 1 | 1 | james | 1 | 2013-8-02 |
|-----------------------------------------+-----------------+-----------+
| 2 | 1 | Jimmy | 0 | 2013-6-25 |
+------------+-------------------+--------+-----------------+-----------+
| 3 | 2 | Manny | 1 | 2013-07-02|
|-----------------------------------------+-----------------+-----------+
| 4 | 1 | Kim | 1 | 2013-09-02|
+------------+-------------------+--------+-----------------+-----------+
Payments table:
+------------+-------------------+--------+-----------------+----------------+
| id | member_id |amount | transaction_id | transferred_at |
+------------+-------------------+--------+-----------------+----------------+
| 1 | 1 | 100 | T1001 | 2013-8-03 |
|-----------------------------------------+-----------------+--------------- +
| 2 | 2 | 0 | null | Null |
+------------+-------------------+--------+-----------------+----------------+
| 3 | 3 | 200 | T1002 | Null |
|-----------------------------------------+-----------------+----------------+
| 4 | 4 | 50 | T1005 | 2013-09-05 |
+------------+-------------------+--------+-----------------+----------------+
How can I select the following?
Expecting the following output:
+------------+-------------------+--------+-----------------+---------------+--------------+
| Org name | Revenue |untransferred amount | Total members | last 30 days |
+------------+-------------------+--------------------------+---------------+--------------+
| AAA | 150 | 0 | 3 | 2 |
|-----------------------------------------------------------+---------------+--------------+
| BBB | 200 | 200 | 1 | 0 |
+------------+-------------------+--------------------------+---------------+--------------+
Org name = organisation name
Revenue = Total amount received
untransferred amount = transferred_at is null (payments table)
Total members = total members joined till today
last 30 days = total members joined last 30 days
You need to join your tables, group the results and select the desired logic:
SELECT org.name,
SUM(pmt.amount) AS revenue,
SUM(IF(pmt.transferred_at IS NULL, pmt.amount, 0)) AS untransferred
FROM Organisations org
JOIN Members mem ON mem.organisation_id = org.id
JOIN Payments pmt ON pmt.member_id = mem.id
GROUP BY org.id
See it on sqlfiddle.
select o.name,
sum(amount) as Revenue,
sum(if(transferred_at is null, amount, 0)) as untransfered_ammt,
sum(if(join_date>=curdate() - interval 30 day, 1, 0)) as last_30_d
from organisations o
inner join members m on o.id=m.organisation_id
inner join payments p on p.member_id=m.member_id
group by 1