Operations with a created table MySQL [duplicate] - mysql

Here is a very basic look at my table. I have columns 1 and 2 and need to generate column 3. Column 3 is simply the total of the Number column for all Name divided by Number for the given row.
| Name | Number | % of total |
| ------------- |:-------------:| -----: |
| Bob | 5 | 25 |
| Sally | 10 | 50 |
| John | 5 | 25 |
I'm struggling with how to get the total of the number row and use this as a value to calculate the rest.
EDIT: I'm looking to do this as a single query instead of two separate if possible.

You just need to CROSS JOIN the SUM() of Number column:
SELECT Name, Number, Number * 100 / t.s AS `% of total`
FROM mytable
CROSS JOIN (SELECT SUM(Number) AS s FROM mytable) t
Demo Here

If I were doing this, I would start by storing a variable that held the total, like this:
SET #total := (SELECT SUM(number) FROM myTable);
Once I had that variable, I could run a query that got the percentage for each row like this:
SELECT name, number, (number / #total) * 100 AS percentage
FROM myTable;
If you don't want to use a variable, you can just move that subquery into your select statement:
SELECT name, number, (number / (SELECT SUM(number) FROM myTable)) * 100 AS percentage
FROM myTable;
Here is an SQL Fiddle example with each approach.

You can get it with a subselect:
SELECT Name, Number, Number * 100 / (select sum(Number) FROM MYTABLE) AS '% of total'
FROM mytable

Related

sql query group by with aggregate

Have the following table as an example:
zipcode | zipsource | patientcount
-----------------------------------
81501 | CMHSP | 10
81503 | CMHSP | 20
81505 | CMHSP | 30
81501 | SMHRMC | 15
81503 | SMHRMC | 25
81505 | SMHRMC | 35
Trying to show only the zipcodes where the patient count is above 20% of total for Source and Source = SMHRMC(normally a parameter but for the example I've selected SMHRMC). Output table as follows:
zipcode | zipsource | patientcount | Total | Percent
--------------------------------------------------------
81503 | SMHRMC | 25 | 75 | 25%
81505 | SMHRMC | 35 | 75 | 47%
I've tried multiple queries but at this point I don't think I'm close. Any ideas?
The query that works is as follows:
select zipcode,
zip_source,
patient_count,
total_count,
patient_count *100/total_count as percentage
from Zip_Count_Source
cross join (select sum(patient_count) as total_count
from zip_count_Source
where zip_source = 'COMHSP') as X
where zip_source = 'COMHSP' and patient_count*100/total_count > 1
But what I'm having issues with now is that Zip_source can be a multi-value parameter so I change the clauses to zip_source in ('COMHSP', 'SMHRMC') and it works but I want to total_count for each source but not the combined for both sources. Group By did not work after the where clause. Thanks for all that have helped.
Try this:
SELECT zipcode, zipsource, patientcount * 100 / total_count
FROM mytable
CROSS JOIN (SELECT SUM(patientcount) AS total_count
FROM mytable
WHERE zipsource = 'SMHRMC') AS x
WHERE zipsource = 'SMHRMC' AND patientcount / total_count > 0.2
The query uses a CROSS JOIN in order to link the total count of patientcount with the table. Using this count we can calculate the percentage, and filter out any rows not exceeding the desired value.
Demo here
This should do the trick
select t1.zipcode,
t1.zipsource,
t1.patientcount,
t2.total,
t1.patientcount / t2.total * 100 as percent
from yourTable t1
join (
select zipcode, sum(patientcount) as total
from yourTable
group by zipcode
) t2
on t1.zipcode = t2.zipcode
where t1.patientcount / t2.total > 0.2
To filter for a single zipsource, you can add a condition to the where clause
where t1.patientcount / t2.total > 0.2 and
t1.zipsource = 'SMHRMC'
When joining to another table, there is commonly a join condition to filter out rows preventing a Cartesian product (the contents of one table multiplied by another). Since the derived table (total) returns a single value, the join condition is unneeded (the contents of table1 multiplied by 1 = table1).
This is acceptable as long as the value represents what you want to express (i.e., remove the where condition and it will produce the grand total of all patients).
select zipcode,
zipsource,
sum(patientcount) as patientcount,
Total,
concat(round(100*sum_patientcount/Total),'%') as `SHRMC_%`
from table1,
(select count(*) as Total
from table1
where zipsource='SHRMC') as total
where zipsource='SHRMC'
group by zipcode
having sum(patientcount)/total >= .2

How to iterate over possible values over values of a column

I have a table, which stores names and numbers associated with it. Each of these numbers are of a certain type. The combination of name and type is unique.
name | type | number
---------------------
a | t0 | 5
a | t1 | 6
b | t0 | 7
c | t1 | 8
And I want this table as a result, which shows the numbers which are associated with that name, regardless of type accumulated.
name | sum
------------
a | 11
c | 8
b | 7
Now I know the SUM() function and I have written this so far:
SELECT name, SUM( ??SELECT name, SUM(number) WHERE name = 'a'?? ) AS sum
FROM table
ORDER BY sum DESC;
The thing is I don't know how to write the inner part of the SUM() function, as I can't use SELECT statements inside of functions. Also I don't know how I can iterate over the possible values of the name column.
SELECT NAME,
Sum(number) As 'Sum'
FROM table
GROUP BY NAME
ORDER BY Sum(number) DESC;
You need to use GROUP BY along with SUM:
SELECT name, SUM(number) AS sum
FROM tableName
GROUP BY name
ORDER BY SUM(number) DESC; -- or ORDER BY sum DESC; - it is identical

sql get couple of elements

I have the following sql table:
| ID | numbers |
|----|-----------------------------|
| 1 | 1,3,19,23,28,32,39,42,60,80 |
| 2 | 1,3,18,24,29,33,40,43,61,80 |
| 3 | 1,2,3,25,30,34,41,44,62,78 |
In Numbers I have a string with 10 numbers.
I want to get all couple of two elements (and if it is possible for three, four etc) in SQL Server or MySQL.
For example for two elements:
1,3 appers in all rows (3 times)
1, 80 appears in the first and second row (2 times)
etc
I tried to split numbers from every row and insert into a temporary table and after generate combinations of 10 choose k (where k is numbers of elements in a couple) but something doesn't work. I don't know if it's the best idea.
My code in this moment: http://pastebin.com/qRjPdfay
Thanks
Yes, splitting your numbers coulmns to rows would make things easier. If you are using MySQL you could use a query like this:
CREATE TABLE mytable2 AS
SELECT
ID, SUBSTRING_INDEX(SUBSTRING_INDEX(numbers, ',', n),',',-1) AS number
FROM
mytable CROSS JOIN (SELECT 1 AS n
UNION ALL SELECT 2 AS n
UNION ALL SELECT 3 AS n
UNION ALL SELECT 4 AS n
UNION ALL SELECT 5 AS n
UNION ALL SELECT 6 AS n
UNION ALL SELECT 7 AS n
UNION ALL SELECT 8 AS n
UNION ALL SELECT 9 AS n
UNION ALL SELECT 10 AS n) d;
(this will work if all numbers contains exactly 10 numbers an no less, if there are less this query needs some improvements). Then you can count the time each number appears:
SELECT number, COUNT(*) as appears
FROM mytable2
GROUP BY number
ORDER BY appears DESC
and you can group number by the number of times they appear:
SELECT
appears, GROUP_CONCAT(number) AS numbers
FROM (
SELECT number, COUNT(*) as appears
FROM mytable2
GROUP BY number
ORDER BY appears DESC
) g
GROUP BY
appears
ORDER BY
appears DESC
(MySQL only) and the result will be like this:
| appears | numbers |
|---------|---------------|
| 3 | 3,1 |
| 2 | 80 |
| 1 | 43,23,40..... |
Please see a fiddle here.

Get column sum and use to calculate percent of total (mySQL)

Here is a very basic look at my table. I have columns 1 and 2 and need to generate column 3. Column 3 is simply the total of the Number column for all Name divided by Number for the given row.
| Name | Number | % of total |
| ------------- |:-------------:| -----: |
| Bob | 5 | 25 |
| Sally | 10 | 50 |
| John | 5 | 25 |
I'm struggling with how to get the total of the number row and use this as a value to calculate the rest.
EDIT: I'm looking to do this as a single query instead of two separate if possible.
You just need to CROSS JOIN the SUM() of Number column:
SELECT Name, Number, Number * 100 / t.s AS `% of total`
FROM mytable
CROSS JOIN (SELECT SUM(Number) AS s FROM mytable) t
Demo Here
If I were doing this, I would start by storing a variable that held the total, like this:
SET #total := (SELECT SUM(number) FROM myTable);
Once I had that variable, I could run a query that got the percentage for each row like this:
SELECT name, number, (number / #total) * 100 AS percentage
FROM myTable;
If you don't want to use a variable, you can just move that subquery into your select statement:
SELECT name, number, (number / (SELECT SUM(number) FROM myTable)) * 100 AS percentage
FROM myTable;
Here is an SQL Fiddle example with each approach.
You can get it with a subselect:
SELECT Name, Number, Number * 100 / (select sum(Number) FROM MYTABLE) AS '% of total'
FROM mytable

Query to Segment Results Based on Equal Sets of Column Value

I'd like to construct a single query (or as few as possible) to group a data set. So given a number of buckets, I'd like to return results based on a specific column.
So given a column called score which is a double which contains:
90.00
91.00
94.00
96.00
98.00
99.00
I'd like to be able to use a GROUP BY clause with a function like:
SELECT MIN(score), MAX(score), SUM(score) FROM table GROUP BY BUCKETS(score, 3)
Ideally this would return 3 rows (grouping the results into 3 buckets with as close to equal count in each group as is possible):
90.00, 91.00, 181.00
94.00, 96.00, 190.00
98.00, 99.00, 197.00
Is there some function that would do this? I'd like to avoid returning all the rows and figuring out the bucket segments myself.
Dave
create table test (
id int not null auto_increment primary key,
val decimal(4,2)
) engine = myisam;
insert into test (val) values
(90.00),
(91.00),
(94.00),
(96.00),
(98.00),
(99.00);
select min(val) as lower,max(val) as higher,sum(val) as total from (
select id,val,#row:=#row+1 as row
from test,(select #row:=0) as r order by id
) as t
group by ceil(row/2)
+-------+--------+--------+
| lower | higher | total |
+-------+--------+--------+
| 90.00 | 91.00 | 181.00 |
| 94.00 | 96.00 | 190.00 |
| 98.00 | 99.00 | 197.00 |
+-------+--------+--------+
3 rows in set (0.00 sec)
Unluckily mysql doesn't have analytical function like rownum(), so you have to use some variable to emulate it. Once you do it, you can simply use ceil() function in order to group every tot rows as you like. Hope that it helps despite my english.
set #r = (select count(*) from test);
select min(val) as lower,max(val) as higher,sum(val) as total from (
select id,val,#row:=#row+1 as row
from test,(select #row:=0) as r order by id
) as t
group by ceil(row/ceil(#r/3))
or, with a single query
select min(val) as lower,max(val) as higher,sum(val) as total from (
select id,val,#row:=#row+1 as row,tot
from test,(select count(*) as tot from test) as t2,(select #row:=0) as r order by id
) as t
group by ceil(row/ceil(tot/3))