I have a SQL database for monthly values with some valuetypeline and value for each month and the problem is when i tried to aggregate the information in the tablix matrix inside an ssrs report
Example of the database
CustomerId | Year | Month | ValueTypeId | Value
---------------------------------------------
1 | 2020 | 1 | 1 | 500
1 | 2020 | 1 | 2 | 10
1 | 2020 | 2 | 1 | 200
1 | 2020 | 2 | 2 | 15
2 | 2020 | 1 | 1 | 100
2 | 2020 | 1 | 2 | 10
2 | 2020 | 2 | 1 | 1500
2 | 2020 | 2 | 2 | 15
And i have created an example of datalabel field for a specific valuetypeid taking into account 2 parameters that i have (Year and Month)
=IIF(Fields!ValueTypeId Value="1" and Fields!Year.Value=Parameters!Year.Value and
Fields!Month.Value=Parameters!Month.Value,CDbl(Fields!ReportingValue.Value),CDbl(0))
When i create a tablix matrix and I put the fields with [Sum(SalesMTD)] imagine Year =2020 and month = 2, the result will be 200+1500 = 1700
And if I create the same table than the example adding the nuew field, the result is something like this.
CustomerId | Year | Month | ValueTypeId | Value | SalesMTD
-----------------------------------------------------------
1 | 2020 | 1 | 1 | 500 | 0
1 | 2020 | 1 | 2 | 10 | 0
1 | 2020 | 2 | 1 | 200 | 200
1 | 2020 | 2 | 2 | 15 | 0
2 | 2020 | 1 | 1 | 100 | 0
2 | 2020 | 1 | 2 | 10 | 0
2 | 2020 | 2 | 1 | 1500 | 1500
2 | 2020 | 2 | 2 | 15 | 0
The problem is when we tried to calculate an average [Avg(SalesMTD)] becasue the system instead of doing this (200+1500)/2 it seams to doing (0+0+200+0+0+0+1500+0)/8. Something that it is wrong for me.
Can someone helpme on this? I have tried averageiff innoring 0 values but i cant finde it, in any case 0 could be a possible value if it is real, i think that the problem is more in the calculation of the field that put 0 in the rows that are not with the conditions when in reality should be ignored or nulls. For sums is valid but i have found that for average or other calculations is not correct.
Thanks in advance
Your problem, are you pointed out is that the AVG() function includes zeros. However, it does not include Null values.
So, if we convert zeros to null values (Nothing in SSRS expressions) then we can fix your issue.
Use the following expression
=Avg(
IIF(Fields!SalesMTD.Value=0, Nothing, Fields!SalesMTD.Value)
)
In the screen shot below, I took your sample data and added a SUM, a standard AVG and finally the expression above (labelled AGV2).
Related
I am getting the following table,
+-------------+-----------+------------+--------------------+
| quantity | year | month | category |
+-------------+-----------+------------+--------------------+
| 122 | 2012 | 7 | 15 |
| 100 | 2012 | 7 | 25 |
| 1029| 2012 | 7 | 10 |
| 212 | 2012 | 7 | 0 |
+-------------+-----------+------------+--------------------+
But I want to get it as how we can merge cells in excel
+-------------+-----------+------------+--------------------+
| quantity | year | month | category |
+-------------+-----------+------------+--------------------+
| 122 | | | 15 |
| 100 | 2012 | 7 | 25 |
| 1029| | | 10 |
| 212 | | | 0 |
+-------------+-----------+------------+--------------------+
checking if this is possible in MySQL?
You might find that aggregation is what you really want:
select year, month, group_concat(quantity), group_concat(category)
from t
group by year, month;
This produces one row for each year/month combination with a list of the quantities and categories. You can get fancy and use a newline to separate the values. They would appear on multiple "lines" but still be one "row".
Note that the ordering is not specified in the question. And without an order by in the group_concat() the values for the two columns might not be in the same order as the original data.
I have a table which saves monthly values, but also a value for the complete year. Is is possible to add to the yearly value whenever I insert a value for a month?
I want to avoid loading the value first, adding to it in the server-code and writing it again.
You can write a trigger and insert value in the years table when any value is inserted in the Month table like
CREATE TRIGGER tr_month ON monthly_table
AFTER INSERT
AS
BEGIN
UPDATE year_table
SET // insert your values here
FROM inserted
WHERE monthly.id = inserted.id; // something like that, I am not sure about your structure thats why cannot add exact syntax
END
GO
Your best approach to this is avoiding redundant data in your table. When you need year totals, SELECT them.
You didn't tell us your table definition, so I will guess. The table months contains
year int (for example, 2019)
month int (1-12)
value number
You can get the details of this the obvious way: `
SELECT year, month, value FROM months;
You can get the details and the yearly sums this way
SELECT year, month, SUM(value) value
FROM months
GROUP BY year, month WITH ROLLUP;
The result set for this query looks like the other result set, but also contains sums. It looks like this:
| year | month | value |
| ---- | ----- | ----- |
| 2018 | 1 | 100 | detail month values...
| 2018 | 2 | 140 |
| 2018 | 3 | 130 |
| 2018 | 4 | 190 |
| 2018 | 5 | 120 |
| 2018 | 6 | 180 |
| 2018 | 7 | 130 |
| 2018 | 8 | 140 |
| 2018 | 9 | 150 |
| 2018 | 10 | 200 |
| 2018 | 11 | 230 |
| 2018 | 12 | 300 |
| 2018 | | 2010 | yearly sum for 2018 (month is NULL)
| 2019 | 1 | 100 |
| 2019 | 2 | 130 |
| 2019 | 3 | 160 |
| 2019 | 4 | 140 |
| 2019 | 5 | 190 |
| 2019 | 6 | 240 |
| 2019 | | 960 | yearly sum for 2019 (month is NULL)
| | | 2970 | total sum (both month and year are NULL)
View on DB Fiddle
Why is this a good process?
you need to store no extra data.
it works correctly even if you update or delete rows in your table.
it's fast: SQL is made to do this kind of thing.
Just solved it by adding the values client side, this also saves computing time on the server.
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 |
+----------------+----------+----------+------------+
EDITED for clarity and added info:
Total newbie to Ruby coding (and coding in general) so please be gentle.
I have a MySQL database, and I want to pull out some data from one of the tables, a column of which is labelled "fulldate".
The following code works to pull out all rows after a certain date.
start_date = Date.new(2018, 1, 2)
end_date = Date.new(2018, 1, 12)
clw_check = client.query('SELECT * FROM rotadates WHERE fulldate >"#{start_date}"')
clw_check.each do |row| puts row["fulldate"] end
Then the output is a list of dates from each row.
However, when I change to
clw_check = client.query('SELECT * FROM rotadates WHERE fulldate <"#{end_date}"')
clw_check.each do |row| puts row["fulldate"] end
then this produces
=> []
If I put the date instead of the #{} expression, then I get a list of dates with both less than and greater than expressions.
I have searched StackOverflow and the net in general, but cannot for the life of me work out why it works with the first expression the second.
A check on whether start_date and end_date are dates or strings says they are dates, and the MySQL column is also a date with identical yyyy-mm-dd format.
Example of rows from MySQL table:
rotadates
| idDate | fulldate | year | month | day | quarter | week | dayOfWeek | weekend | clw |
| 20180102 | 2018-01-02 | 2018 | 1 | 2 | 1 | 1 | 2 | 0 | 1 |
| 20180103 | 2018-01-03 | 2018 | 1 | 3 | 1 | 1 | 3 | 0 | 1 |
| 20180104 | 2018-01-04 | 2018 | 1 | 4 | 1 | 1 | 4 | 0 | 1 |
| 20180105 | 2018-01-05 | 2018 | 1 | 5 | 1 | 1 | 5 | 0 | 1 |
| 20180106 | 2018-01-06 | 2018 | 1 | 6 | 1 | 1 | 6 | 1 | 1 |
I have no idea why but when I pass this in IRB it does not seem to work whereas in Aptana console it does.
This question already has an answer here:
MySQL pivot row into dynamic number of columns
(1 answer)
Closed 5 years ago.
I'm looking at some keyword rankings and need to bring back data on the number of keywords a URL has increased rank for, decreased rank for, stayed the same for. My data looks like this:
URL | Keyword | Position | Previous position | Keyword Movement
example.com/page1 | things to do london | 38 | 101| Up
example.com/page2 | mens shoes size 8 | 48 | 94 | Up
example.com/page3 | notebooks | 22 | 2 | Down
example.com/page4 | macbook pros for sale | 52 | 52 | Same
example.com/page1 | homebrew supplies | 56 | 46 | Down
example.com/page2 | sql tutorials | 70 | 39 | Down
example.com/page3 | random seo keywords | 88 | 36 | Down
example.com/page4 | best albums of 2017 | 94 | 95 | Up
example.com/page5 | fender stratocaster | 19 | 9 | Down
example.com/page6 | qotsa | 91 | 34 | Down
I'd like to have a table showing the URL, number of keyword increases, no. of keyword decreases, and no. of keywords staying the same. In Excel this can be done with a countif formula but not sure how to do this with mysql. I'd like a table looking like the following:
URL |Keywords Up |Keywords Down |Keywords remain
example.com/page1 | 1 | 1 | 0
example.com/page2 | 1 | 1 | 0
example.com/page3 | 0 | 2 | 0
example.com/page4 | 1 | 0 | 1
example.com/page5 | 0 | 1 | 0
example.com/page6 | 0 | 1 | 0
I'm looking for a way of doing a countif on the "Movement" column.
Thanks.
You can use condtional aggregation here on the Movement column and tally the three types of movements, grouping by URL.
SELECT
URL,
SUM(CASE WHEN Movement = 'Up' THEN 1 ELSE 0 END) AS keywords_up,
SUM(CASE WHEN Movement = 'Down' THEN 1 ELSE 0 END) AS keywords_down,
SUM(CASE WHEN Movement = 'Same' THEN 1 ELSE 0 END) AS keywords_remain
FROM yourTable
GROUP BY URL