I have the following statement
TRANSFORM Sum(revenue) AS sum_revenue
SELECT year
FROM revenues
GROUP BY year
PIVOT month;
Which gives me a table like
year | 1 | 2 | ... | 11 | 12
------------------------------------------
2013 | 5000 | 6000 | ... | 5000 | 6000
2014 | 5000 | 6000 | ... | 5000 | 6000
2015 | 5000 | 6000 | ... | 5000 | 6000
I would like to add a total column at the end like this:
year | 1 | 2 | ... | 11 | 12 | total
--------------------------------------------------
2013 | 5000 | 6000 | ... | 5000 | 6000 | 75000
2014 | 5000 | 6000 | ... | 6000 | 6000 | 80000
2015 | 5000 | 6000 | ... | 6000 | 7000 | 85000
How can I achieve this?
If you had used the Query Wizard it should have built it for you by default, unless you have checked it not to include "Totals" column. However you can manually add it, by going to the design view and adding this,
TRANSFORM
Sum(revenue) AS sum_revenue
SELECT
[year],
Sum(revenue) As [Total Of SumRevenue]
FROM
revenues
GROUP BY
[year]
PIVOT
[month];
PS: I played with the query, I get the right result. Not sure why yours is not !
Related
I am struggling to find a way to efficently join two datasets using a single query
Dataset one can be returned using the following query:
SELECT hours_person_id, hours_date, hours_job, SUM(hours_value) AS hours
FROM hours
WHERE hours_status = 1
GROUP BY hours_person_id, hours_date, hours_job
which gives a dataset similar to
| 1 | 2020-06-07 | 101 | 25 |
| 1 | 2020-06-07 | 102 | 10 |
| 1 | 2020-06-07 | 103 | 5 |
| 2 | 2020-06-07 | 101 | 30 |
| 2 | 2020-06-07 | 104 | 10 |
From which we can get total hours per week, per job, etc...
Our second dataset gives us the hourly rates for the each person. The problem is that this table contains both historical and future hourly rates, so the join needs to ensure that the rate applies to the correct person_id and date. There could also be more than 1 rate for a person on a date.
The following gives all the rates that are active
SELECT rate_person_id, rate_date, rate_value
FROM rates
WHERE rate_active = 1
Which could look like
| 1 | 2020-01-01 | 20.00 |
| 1 | 2020-05-01 | 25.00 |
| 1 | 2020-07-01 | 22.00 |
| 2 | 2020-01-01 | 22.00 |
| 2 | 2020-05-01 | 24.00 |
| 3 | 2020-05-01 | 20.00 |
| 3 | 2020-05-01 | 21.00 |
| 3 | 2020-07-01 | 18.00 |
So for the hours above the rate from the 2020-05-01 would be the expected result, with the 21.00 value being the result for person_id === 3
Can what I am looking for be done in a single Query, or am I better off Joining two subqueries?
Update
As requested here is a fiddle that represents the above
https://www.db-fiddle.com/f/oiUpTnajY6M6ZTfZgRf4kT/0
As you can see we have a query that returns the correct data, but this query does not scale to our curennt data set (1.8m lines and more sub tables)
So for the hours above the rate from the 2020-05-01 would be the expected result, with the 21.00 value being the result for person_id === 1
From your rates output, person_id = 1 was never on rate value 21.00 .
| 1 | 2020-01-01 | 20.00 |
| 1 | 2020-05-01 | 25.00 |
| 1 | 2020-07-01 | 22.00 |
For 2 active rates for a person, do you need the most recent rate or you need the rate in the month where he worked. If there is no rate for that month then do you want 0 rate or something else.
SELECT h.*,
(SELECT rate_value
FROM rates r
WHERE h.hours_person_id = r.rate_person_id AND
r.date <= h.date
ORDER BY r.date DESC
LIMIT 1
) as rate_value
FROM hours h
I don't see what active has to do with the question, because you need to go back in time. You can then aggregate or do whatever you want once you have the correct rate on the date.
I am developing a booking engine web app.
Once an user made a booking it goes to this table.
id | Promo_code | total | arrival_date | departure_date | booked_date
1 | ABC1 | 1000 | 2019-02-06 | 2019-02-10 | 2019-02-02
2 | ABC1 | 2500 | 2019-02-07 | 2019-02-11 | 2019-02-03
3 | ABC1 | 3000 | 2019-02-12 | 2019-02-15 | 2019-02-03
4 | ABC2 | 5000 | 2019-02-07 | 2019-02-11 | 2019-02-02
5 | null | 3000 | 2019-02-12 | 2019-02-15 | 2019-02-01
Here the promo_code is what it names implies. If the user doesn't book with a promo_code it is null (5th record).
Hope other fields total, arrival_date, departure_date and booked_date are clear to you.
My question is I want to generate a report something like this.
promo_code | number_of_bookings | revenue | Average_length_of_stay | Average_depart_date | Average_reservation_revenue
ABC1 | 3 | 6500 | 3 | 5 | 2166
ABC2 | 1 | 5000 | 4 | 5 | 5000
This report is called revenue by promo code report.
If I explain what happend in this report is
Average_length_of_stay = (departure_date - arrival_date) / number_of_bookings
Average_depart_date = (departure_date - booked_date) / number_of_bookings
Of cause I could generate this report by the backend logic somehow. But I would be very painful. There must be a way to query this
in the SQL directly.
What I have done upto now is
SELECT promo_code ,count(*) as number_of_bookings,
sum(total) as revenue
FROM booking_widget.User_packages group by promo_code;
I am stuck with Average_length_of_stay, Average_depart_date and Average_reservation_revenue.
How do I get the average values which the group by clause?
It is trivial:
SELECT promo_code
, COUNT(*) AS number_of_bookings
, SUM(total) AS revenue
, AVG(DATEDIFF(departure_date, arrival_date)) AS average_length_of_stay
, AVG(DATEDIFF(departure_date, booked_date)) AS average_depart_date
, AVG(total) AS average_reservation_revenue
FROM t
GROUP BY promo_code
I have a database that tracks the size of claims.
Each claim has fixed information that is stored in claim (such as claim_id and date_reported_to_insurer).
Each month, I get a report which is added to the table claim_month. This includes fields such as claim_id, month_id [101 is 31/01/2018, 102 is 28/02/2018, etc] and paid_to_date.
Since most claims don't change from month to month, I only add a record for claim_month when the figure has changed since last month. As such, a claim may have a June report and an August report, but not a July report. This would be because the amount paid to date increased in June and August, but not July.
The problem that I have now is that I want to be able to check the amount paid each month.
Consider the following example data:
+----------------+----------+----------------+--------------+
| claim_month_id | claim_id | month_id | paid_to_date |
+----------------+----------+----------------+--------------+
| 1 | 1 | 6 | 1000 |
+----------------+----------+----------------+--------------+
| 5 | 1 | 7 | 1200 |
+----------------+----------+----------------+--------------+
| 7 | 2 | 6 | 500 |
+----------------+----------+----------------+--------------+
| 12 | 1 | 9 | 1400 |
+----------------+----------+----------------+--------------+
| 18 | 2 | 8 | 600 |
+----------------+----------+----------------+--------------+
If we assume that this is all of the information regarding claim 1 and 2, then that would suggest that they are both claims that occurred during June 2018. Their transactions should look like the following:
+----------------+----------+----------------+------------+
| claim_month_id | claim_id | month_id | paid_month |
+----------------+----------+----------------+------------+
| 1 | 1 | 6 | 1000 |
+----------------+----------+----------------+------------+
| 5 | 1 | 7 | 200 |
+----------------+----------+----------------+------------+
| 7 | 2 | 6 | 500 |
+----------------+----------+----------------+------------+
| 12 | 1 | 9 | 200 |
+----------------+----------+----------------+------------+
| 18 | 2 | 8 | 100 |
+----------------+----------+----------------+------------+
The algorithm I'm using for this is
SELECT claim_month_id,
month_id,
claim_id,
new.paid_to_date - old.paid_to_date AS paid_to_date_change,
FROM claim_month AS new
LEFT JOIN claim_month AS old
ON new.claim_id = old.claim_id
AND ( new.month_id > old.month_id
OR old.month_id IS NULL )
GROUP BY new.claim_month_id
HAVING old.month_id = Max(old.month_id)
However this has two issues:
It seems really inefficient at dealing with claims with multiple
records. I haven't run any benchmarking, but it's pretty obvious.
It doesn't show new claims. In the above example, it would only show lines 2, 3 and 5.
Where am I going wrong with my algorithm, and is there a better logic to use to do this?
Use LAG function to get the next paid_to_date of each claim_id, and use the current paid_to_date minus the next paid_to_date.
SELECT
claim_month_id,
claim_id,
month_id,
paid_to_date - LAG(paid_to_date, 1, 0) OVER (PARTITION BY claim_id ORDER BY month_id) AS paid_month
FROM claim
The output table is:
+----------------+----------+----------+------------+
| claim_month_id | claim_id | month_id | paid_month |
+----------------+----------+----------+------------+
| 1 | 1 | 6 | 1000 |
| 5 | 1 | 7 | 200 |
| 12 | 1 | 9 | 200 |
| 7 | 2 | 6 | 500 |
| 18 | 2 | 8 | 100 |
+----------------+----------+----------+------------+
I have a table named nca_totals.
Table: nca_totals
+----------+-----------+------------+--------------+
| total_id | nca_total | nca_date | account_type |
+----------+-----------+------------+--------------+
| 13 | 10450 | 2015-01-21 | DBP-TRUST |
| 14 | 5000 | 2015-02-05 | DBP-TRUST |
| 15 | 7000 | 2015-04-02 | DBP-TRUST |
| 16 | 4000 | 2015-05-02 | DBP-TRUST |
+----------+-----------+------------+--------------+
Now I want to display all the data by quarter base on its date. Let's say I want to display all the records who belong to 1st Quarter like this:
+----------+-----------+------------+--------------+
| total_id | nca_total | nca_date | account_type |
+----------+-----------+------------+--------------+
| 13 | 10450 | 2015-01-21 | DBP-TRUST |
| 14 | 5000 | 2015-02-05 | DBP-TRUST |
+----------+-----------+------------+--------------+
This date belongs to the 1st quarter of the year (Jan, Feb, March). I only have this query to select the date and return its quarter number as:
SELECT QUARTER('2015-01-11'); /* returns 1 */
How can I combine that query to display all the records by quarter ? Can anyone help ? Thanks.
select *
from nca_totals
where QUARTER(nca_date) = 1
SELECT
CEIL(MONTH(`nca_date`) / 3) AS `quarter`
FROM `nca_totals`;
I have a table with a schema similar to the following
id | year | month | amount ...
x | 2011 | 12 | 312
x | 2011 | 12 | 213
x | 2012 | 1 | 123
x | 2012 | 1 | 123
x | 2012 | 2 | 123
...
I want to know if it would be possible (via mysql) to output something like
year | 1 | 2 | 3 | ....
2011 | 321 | 231 | ...
2012 | 246 | 123 | ...
So doing a group by year, month, sum(amount) and output one "row" per year with the individual months as the columns.
Thanks
You would want to use a pivot table of sorts. If you are only dealing with months something like the below SQL should work for you. I only did the first three months but the rest are the same.
SELECT year, SUM(IF(month=1,amount,0)) As '1', SUM(IF(month=2,amount,0)) As '2', SUM(IF(month=3,amount,0)) As '3' FROM mytable GROUP BY year