I have a query that pulls the total number of records grouped by the year and length of characters in the identification number. I want to add a column that calculates the percentage of this total against the total for each record year.
This is the query that I am using, and so far I'm able to pull the year, ID length, and the number of records; however, I'm unable to pull the percentage of the total, grouping by the year:
/* Assess length of McrCertID_112 field for 2020. Count the number and percent of records: */
SELECT
DemoRateYear_101,
length(McrCertId_112),
count(*) AS 'Num_of_Records',
concat((count(*) / (SELECT count(*) FROM upl_db_prod.tblProviderDetails) * 100), '%') AS 'Percentage'
FROM upl_db_prod.tblProviderDetails
GROUP BY length(McrCertId_112), DemoRateYear_101
ORDER BY DemoRateYear_101, length(McrCertId_112);
This is what I want the final table to look like:
DemoRateYear_101 length(McrCertId_112) Num_of_Records Percentage
2017 4 10 47.6190%
2017 5 11 52.3809%
2018 4 8 26.6667%
2018 5 10 33.3333%
2018 7 12 40.0000%
Is there a way I can accomplish this in one query? Thank you for looking!
If window functions are available you can do this:
SELECT
demorateyear_101,
LENGTH(mcrcertid_112),
COUNT(*) AS num_of_records,
COUNT(*) / SUM(COUNT(*) OVER (PARTITION BY demorateyear_101)) * 100 AS percentage
FROM tblproviderdetails
GROUP BY demorateyear_101, LENGTH(mcrcertid_112)
ORDER BY demorateyear_101, LENGTH(mcrcertid_112);
Otherwise a subquery is needed (where clause, if any, must match):
SELECT
demorateyear_101,
LENGTH(mcrcertid_112),
COUNT(*) AS num_of_records,
COUNT(*) / (
SELECT COUNT(*)
FROM tblproviderdetails AS x
WHERE x.demorateyear_101 = tblproviderdetails.demorateyear_101
) * 100 AS percentage
FROM tblproviderdetails
GROUP BY demorateyear_101, LENGTH(mcrcertid_112)
ORDER BY demorateyear_101, LENGTH(mcrcertid_112);
Related
SQL Query I Am Working With
Result from the table
What I am trying to accomplish is that instead of just having values for places where num_opens is actually counted, I would want to have it show all potential num_opens values between the minimum and maximum value, and their total to be 0. For example, in the photo we see a jump between
num_opens: 7 Total: 1
num_opens: 10 Total: 1
But I would like it to be
num_opens: 7 Total: 1
num_opens: 8 Total: 0
num_opens: 9 Total: 0
num_opens: 10 Total: 1
and similarly for all potential num_opens values between the minimum and maximum (11 - 15, 15 - 31, 31 - 48). It is tricky because everyday the maximum value could be different (today the max is 48, but tomorrow it could be 37), so I would need to pull the max value somehow.
Thank you!
You can use generate_array() and unnest():
select num_opens, count(t.num_opens)
from (select min(num_opens) as min_no, max(num_opens) as max_no
from t
) x cross join
unnest(generate_array(t.min_no, t.max_no)) num_opens left join
t
on t.num_opens = num_opens
group by num_opens;
You need a reference table to start with. From your picture you have something called users, but really any (big enough) table will do.
So to start, you'll build the reference table using a rank() or row_count() function. Or if your users.id has no gaps it's even easier to use that.
SELECT *, rank() OVER (ORDER BY id) as reference_value FROM users
This will generate a table 1....n for users.
Now you join onto that, but count from the joined in table:
SELECT
a.reference_value, count(b.num_opens) as total
FROM
(SELECT rank() OVER (ORDER BY id) as reference_value from users) a
LEFT JOIN
[whatever table] b ON a.reference_value = b.num_opens
GROUP BY
a.reference_value
But this is too many rows! You definitely have more users than these event counts. So throw a quick filter in there.
SELECT
a.reference_value, count(b.num_opens) as total
FROM
(SELECT rank() OVER (ORDER BY id) as reference_value from users) a
LEFT JOIN
[whatever table] b ON a.reference_value = b.num_opens
WHERE
a.reference_value <= (SELECT max(num_opens) FROM [whatever table])
GROUP BY
a.reference_value
I really am struggling with a MySQL query, I have a table named 'info' and in it I have a column called 'rating' in it I have ratings between 1-10.
Now I need to generate a percentage value of how many ratings are from 1-6 and 7-8 and 9-10 but I need them to display desperately and after that I need a second query that can subtract the percentage value of the results from 1-6 and 9-10.
The query below is as close as I could get from all my research however I don't know how to get a percentage of ratings 1-6 only and not all of them and also how to get a second query to subtract the 1-6 and 9-10 rating percentages. Any help would be amazing.
SELECT rating,
COUNT(*) AS Count,
(COUNT(*) / _total ) * 100 AS Percentege
FROM info,
(SELECT COUNT(*) AS _total FROM info) AS myTotal
GROUP BY rating
Try this:
select if(rating between 1 and 6, '1-6',
if( rating between 7 and 8, '7-8',
'9-10' )
) as rating_range,
count(1) as num
from info
group by rating_range
fiddle code
I have one table with two columns (client_id and spent). Each client bought something more than 20 times. I want to sum spendings for each client.
I know that I can use sum and group by to do that, but I want to use sum not for all values in the groups but for only first 10 values. How can I do that?
I have tried with top 10 and limit 10, but It does not work.
I have 10 different clients and more than 200 rows. Clients are not scattered, they are in order, so I have 20 rows on client1 than 20 rows of on client2... Each client appears more than 20 times. I want to use sum and group by, but I do not want to sum all values (more than 20 for each row) , i want to sum first 10 values. Its ordered by time for each client
select client_id, sum(spendings)
from my_table
group by client_id
If you are using Mysql 8.0, You can do this by using window function.
select client_id, sum(spendings)
from (select client_id, spendings, row_number() over (partition by client_id order by <timecol>) rn
from my_table) t
where rn < 11
group by client_id
For MySQL, try this following code-
SELECT client_id,SUM(spendings)
FROM
(
select client_id,
spendings,
#row_num :=IF(client_id = #client_id,#row_num+1,1)AS RowNumber,
#client_id := client_id
FROM my_table
ORDER BY client_id
-- You may need to add here appropriate ordering
-- To get your desired 10 rows for group by in the result
)A
WHERE A.RowNumber < 11
GROUP BY client_id
I have a query that returns following values:
TemplateCode Total
1418 35
7419 31
7418 31
8325 17
15623 17
4997 17
I want all the rows with top 3 Total values
In my query if I include LIMIT 3 in the query then it gives only 3 which I don't want. I don't want to include LIMIT because count may vary from time to time.
How can I include condition on Total and always get top 3 count values
My current query is like:
select TemplateCode, count(*) as Total from table group by TemplateCode
order by Total desc
limit 3
I think this does what you want:
select t.*
from t
where t.Total >= (select distinct t2.Total
from t t2
order by t2.Total desc
limit 2, 1
);
This assumes that you want the third distinct value. If you just want the third value, remove the distinct.
You could use a inner join on subquery for the top 3 total
select m.TemplateCode , m.total
from my_table m
inner join (
select Total
from my_table
order by Total Desc
limit 3
) t on t.total = m.total
order by m.total, m.TemplateCode
Using MySQL, I am counting the occurrence of several events (fields) over a time span of years. I then display this in columns by year. My query works perfect when grouped by year. I now want to add a final column which displays the aggregate of the years. How do I include the total of columns query?
Event 2008 2009 2010 2011 total
A 0 2 0 1 3
B 1 2 3 0 6
etc.
Here is the real query:
select
count(*) as total_docs,
YEAR(field_document_date_value) as doc_year,
field_document_facility_id_value as facility,
IF(count(IF(field_document_type_value ='LIC809',1, NULL)) >0,count(IF(field_document_type_value ='LIC809',1, NULL)),'-') as doc_type_LIC809,
IF(count(IF(field_document_type_value ='LIC9099',1, NULL)) >0,count(IF(field_document_type_value ='LIC9099',1, NULL)),'-') as doc_type_LIC9099,
IF(count(field_document_f1_value) >0,count(field_document_f1_value),'-') as substantial_compliance,
IF(count(field_document_f2_value) >0,count(field_document_f2_value),'-') as deficiencies_sited,
IF(count(field_document_f3_value) >0,count(field_document_f3_value),'-') as admin_outcome_809,
IF(count(field_document_f4_value) >0,count(field_document_f4_value),'-') as unfounded,
IF(count(field_document_f5_value) >0,count(field_document_f5_value),'-') as substantiated,
IF(count(field_document_f6_value) >0,count(field_document_f6_value),'-') as inconclusive,
IF(count(field_document_f7_value) >0,count(field_document_f7_value),'-') as further_investigation,
IF(count(field_document_f8_value) >0,count(field_document_f8_value),'-') as admin_outcome_9099,
IF(count(field_document_type_a_value) >0,count(field_document_type_a_value),'-') as penalty_type_a,
IF(count(field_document_type_b_value) >0,count(field_document_type_b_value),'-') as penalty_type_b,
IF(sum(field_document_civil_penalties_value) >0,CONCAT('$',sum(field_document_civil_penalties_value)),'-') as total_penalties,
IF(count(field_document_noncompliance_value) >0,count(field_document_noncompliance_value),'-') as total_noncompliance
from rcfe_content_type_facility_document
where YEAR(field_document_date_value) BETWEEN year(NOW()) -9 AND year(NOW())
and field_document_facility_id_value = :facility
group by doc_year
You can not GROUP row twice in a SELECT, so you can only count row in a year or in total. You can UNION two SELECT (one grouped by year, second not grouped - total) to overcome this limitation, but I think it is better to count total from year result in script if there is any.
Simplified example:
SELECT by_year.amount, years.date_year FROM
-- generating years pseudo table
(
SELECT 2008 AS date_year
UNION ALL SELECT 2009
UNION ALL SELECT 2010
UNION ALL SELECT 2011
) AS years
-- joining with yearly stat data
LEFT JOIN
(
SELECT SUM(value_field) AS amount, YEAR(date_field) AS date_year FROM data
GROUP BY YEAR(date_field)
) AS by_year USING(date_year)
-- appending total
UNION ALL SELECT SUM(value_field) AS amount, 'total' AS date_year FROM data
WITH ROLLUP is your friend:
http://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html
Use your original query and simply add this to the last line:
GROUP BY doc_year WITH ROLLUP
That will add a final cumulative row to your query's result set.