How to keep range values in database - mysql

To check a patient's status in a medical test(high, low, average), I have to keep range values for the tests in a table
For a test there can be several ranges.
| range | status |
|-----------|---------|
| 0 - 100 | Low |
| 101- 200 | Average |
| 201 - 300 | High |
For another test, ranges can be different according to the gender
| range | Gender | status |
|-----------|--------|---------|
| 0 - 100 | Male | Low |
| 0 - 105 | Female | Low |
| 100- 200 | Male | Average |
| 105 - 210 | Female | Average |
| 200 - 300 | Male | High |
| 210 - 300 | Female | High |
There can be range data as age, gender, status as well.
How can I map the ranges in database which enables to check which range user is in for a given test result. As an example For a Sugar Test a male user may have a result 45. I need whether the test value is high, low or average.
My initial table solution is shown below. I don't think this is a good solution.
| test | min_age | max_age | range_upper | range_lower | Gender | status |
|------|---------|---------|-------------|-------------|--------|---------|
| 1 | 1 | 10 | 0 | 100 | Male | Low |
| 1 | 1 | 10 | 100 | 200 | Male | Average |
| 1 | 1 | 10 | 200 | 300 | Male | High |
| 1 | 1 | 10 | 0 | 100 | Female | Low |
| 1 | 1 | 10 | 100 | 200 | Female | Average |
| 1 | 1 | 10 | 200 | 300 | Female | High |
Please sorry for my English.

Why do not use range reference instead of pair of values?
Table status_ranges
| id | range_min | range_max | status |
|----|-----------|-----------|---------|
| 1 | 0 | 100 | Low |
| 2 | 101 | 200 | Average |
| 3 | 201 | 300 | High |
Table of tests
| test | value_1 | gender | id_status_of_value_1 | . . .
|------|---------|--------|----------------------|-----
| 1 | 10 | Male | 1 | . . .
| 1 | 120 | Male | 2 |
| 1 | 235 | Male | 3 |
| . . .

Related

sum and calculate average in Mysql

Assuming that I have a table like this
| id | name | code | method | account | time | date |
|----|--------|------|--------|---------|------|------------|
| 1 | name01 | 200 | GET | 1 | 100 | 2020-06-10 |
| 2 | name01 | 201 | GET | 2 | 150 | 2020-06-10 |
| 3 | name02 | 200 | POST | 4 | 200 | 2020-06-10 |
| 4 | name01 | 200 | GET | 5 | 250 | 2020-06-11 |
| 5 | name02 | 200 | POST | 1 | 300 | 2020-06-11 |
How can I select an exact date range and get the sum of account and average of time?
Notice that same name but different code should be configured as different group.
e.g. select date range 2020-06-10 to 2020-06-11
return:
| name | code | method | account | time |
|--------|------|--------|---------|------|
| name01 | 200 | GET | 6 | 175 |
| name01 | 201 | GET | 2 | 150 |
| name02 | 200 | POST | 5 | 250 |
And if I select the same day like this: 2020-06-10 to 2020-06-10
just return:
| name | code | method | account | time |
|--------|------|--------|---------|------|
| name01 | 200 | GET | 1 | 100 |
| name01 | 201 | GET | 2 | 150 |
| name02 | 200 | POST | 4 | 200 |
You want aggregation:
select
name,
code,
method,
sum(account) account,
avg(time) time
from mytable
where date between '2020-06-10' and '2020-06-11'
group by name, code, method

Output record without duplicate

I have a table like this and i want to output without duplication of the same user. If i use group by it shows only one record on the same column. iam also using left join for location and user name. A little help
+------+---------+----------+---------+
| user | work id | location | time |
+------+---------+----------+---------+
| 1 | 42 | 1 | 2hr |
| 1 | 42 | 1 | 10min |
| 1 | 42 | 1 | 30min |
| 2 | 42 | 1 | 4hr |
| 2 | 42 | 1 | 2.30min |
| 1 | 50 | 2 | 4min |
| 1 | 50 | 2 | 5min |
| 2 | 20 | 3 | 3hr |
| 1 | 20 | 3 | 6hr |
+------+---------+----------+---------+
Iam looking for this
+------+---------+----------+
| user | work id | location |
+------+---------+----------+
| 1 | 42 | 1 |
| 1 | 50 | 2 |
| 1 | 20 | 3 |
| 2 | 42 | 1 |
| 2 | 20 | 3 |
+------+---------+----------+
You simply need a distinct clause here -
SELECT DISTINCT user
,workid
,location
FROM YOUR_TABLE
ORDER BY user
,location

How to combine results from 2 queries without common "GROUP BY" element

I am trying to count the number of instances of different types and group them by a field denoting location. However, the location from my second query is obtained by a sub string of yet another field and is 300 less than the desired number.
The goal is to sum phone types by location. For IP phones (type 9608, b189, and 9611), the location is determined by the nr (network region). For analog devices (type cordless, 2500, and fax) the location is determined by the first 3 characters on the port.
I have each individual query working, for the most part, as desired. I have 2 issues:
The nr from the second query needs to have 300 added to the result.
I have not been able to combine the 2 queries together to obtain the desired, single result.
Example Data Set
+------+--------------+---------+-----------------------------+------+------+-----------+------+------+--------+-----------+------+----------------+------+
| id | extension | port | name | cp1 | cor | type | cp2 | cos | tenent | prod_id | tcp | ip | nr |
+------+--------------+---------+-----------------------------+------+------+-----------+------+------+--------+-----------+------+----------------+------+
| 62 | 111-000-0201 | S00215 | Baker Mail Rm | | 2 | 9608 | | 1 | 4 | IP_Phone | tcp | 172.20.94.76 | 308 |
| 63 | 111-000-0202 | S00216 | Baker Copy Rm | | 2 | 9608 | | 1 | 4 | | | | |
| 66 | 111-000-0205 | S00235 | Baker Conference Rm 2 | | 2 | b189 | | 1 | 4 | IP_Phone | tcp | 172.20.94.22 | 308 |
| 123 | 111-000-0626 | 008V301 | Baker Cordless | | 2 | cordless | | 1 | 1 | | | | |
| 145 | 111-000-1200 | S12329 | JEF-MAIN Dental 1 | | 2 | 9611 | | 1 | 1 | IP_Phone | tcp | 172.20.195.160 | 490 |
| 885 | 999-888-3025 | 190V203 | JEF WP Admin Conf Rm | | 2 | 2500 | | 1 | 1 | | | | |
| 890 | 999-888-1561 | 190V201 | JEF-GATO Clinic Fax | | 2 | fax | | 1 | 1 | | | | |
| 993 | 111-777-0202 | S00256 | Test Rm | | 2 | 9608 | | 1 | 4 | IP_Phone | | 172.20.190.45 | 303 |
| 994 | 111-777-0212 | S00217 | Test Rm 2 | | 2 | 9608 | | 1 | 4 | IP_Phone | | 172.20.190.46 | 303 |
Query 1
SELECT nr,
sum(type='9608') '9608',
sum(type='9611') '9611',
sum(type='b189') 'b189',
count(*) 'Total IP'
FROM station GROUP BY nr;
Result 1
+------+------+------+------+----------+
| nr | 9608 | 9611 | b189 | Total IP |
+------+------+------+------+----------+
| 308 | 1 | 0 | 1 | 2 |
| 490 | 0 | 1 | 0 | 1 |
| 303 | 2 | 0 | 0 | 2 |
Query 2
SELECT SUBSTR(port, 1, 3) AS 'nr',
sum(type='fax') 'fax',
sum(type='2500') 'analog',
sum(type='cordless') 'cordless',
count(*) 'Total Analog'
FROM station
WHERE port LIKE '___V%'
GROUP BY SUBSTR(port, 1, 3);
Result 2
+------+------+--------+----------+--------------+
| nr | fax | analog | cordless | Total Analog |
+------+------+--------+----------+--------------+
| 008 | 0 | 0 | 1 | 1 |
| 190 | 1 | 1 | 0 | 2 |
The desired result is
+------+------+------+------+----------+------+--------+----------+--------------+
| nr | 9608 | 9611 | b189 | Total IP | fax | analog | cordless | Total Analog |
+------+------+------+------+----------+------+--------+----------+--------------+
| 308 | 1 | 0 | 1 | 2 | 0 | 0 | 1 | 1 |
| 490 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 2 |
| 303 | 2 | 0 | 0 | 2 | 0 | 0 | 0 | 0 |
Is this what you need? I used inner join. check my answer.
SELECT s1.nr,
sum(type='9608') '9608',
sum(type='9611') '9611',
sum(type='b189') 'b189',
count(*) 'Total IP' ,
fax,
analog,
cordless,
TotalAnalog
FROM station s1
INNER JOIN (
SELECT SUBSTR(port, 1, 3) AS 'nr',
sum(type='fax') 'fax',
sum(type='2500') 'analog',
sum(type='cordless') 'cordless',
count(*) 'TotalAnalog'
FROM station
WHERE port LIKE '___V%'
GROUP BY SUBSTR(port, 1, 3)
) as s2
ON s1.nr = s2.nr + 300
GROUP BY nr;
working Fiddle

MySQL Query for averages

good morning. I have this table:
mysql> select * from Data;
+---------------------------+--------+-------+
| affyId | exptId | level |
+---------------------------+--------+-------+
| 31315_at | 3 | 250 |
| 31324_at | 3 | 91 |
| 31325_at | 1 | 191 |
| 31325_at | 2 | 101 |
| 31325_at | 4 | 51 |
| 31325_at | 5 | 71 |
| 31325_at | 6 | 31 |
| 31356_at | 3 | 91 |
| 31362_at | 3 | 260 |
| 31510_s_at | 3 | 257 |
| 5321_at | 4 | 90 |
| 5322_at | 4 | 90 |
| 5323_at | 4 | 90 |
| 5324_at | 3 | 57 |
| 5324_at | 4 | 90 |
| 5325_at | 4 | 90 |
| AFFX-BioB-3_at | 3 | 97 |
| AFFX-BioB-5_at | 3 | 20 |
| AFFX-BioB-M_at | 3 | 20 |
| AFFX-BioB-M_at | 5 | 214 |
| AFFX-BioB-M_at | 7 | 20 |
| AFFX-BioB-M_at | 8 | 40 |
| AFFX-BioB-M_at | 9 | 20 |
| AFFX-HSAC07/X00351_M_at | 3 | 86 |
| AFFX-HUMBAPDH/M33197_3_st | 3 | 277 |
| AFFX-HUMTFFR/M11507_at | 3 | 90 |
| AFFX-M27830_3_at | 3 | 271 |
| AFFX-MurIL10_at | 3 | 8 |
| AFFX-MurIL10_at | 5 | 8 |
| AFFX-MurIL10_at | 6 | 4 |
| AFFX-MurIL2_at | 3 | 20 |
| AFFX-MurIL4_at | 5 | 78 |
| AFFX-MurIL4_at | 6 | 20 |
| U95-32123_at | 1 | 128 |
| U95-32123_at | 2 | 128 |
| U98-40474_at | 1 | 57 |
| U98-40474_at | 2 | 57 |
+---------------------------+--------+-------+
37 rows in set (0.00 sec)
If I wanna look for the average expression level (level) of each array probe (affyId) across all experiments, I do SELECT affyId, AVG(level) AS average FROM Data GROUP BY affyId;
However, I can't figure out how to look for the average expression level of each array probe (affyId) for each experiment... It must be something similar to the last query, but I don't obtain good results... any help?
PD: someone told me I should give some reputation or click to some green button if somebody solves my question... Is it right? How do I do it? I'm pretty new on this website...
This shows the average for every affyId:
SELECT affyId, AVG(level) AS average FROM Data GROUP BY affyId
This the average for every exptId:
SELECT exptId, AVG(level) AS average FROM Data GROUP BY exptId
and this the average for every exptId in every affyId:
SELECT affyId, exptId, AVG(level) AS average FROM Data GROUP BY exptId, affyId
Just add that to the group by clause
SELECT affyId, exptId, AVG(level) AS average
FROM Data
GROUP BY affyId, exptId;

Left join with some field from the same source field and table but different condition in MySQL

I have tables that look like this:
ProductList
+------+----------------+--------------+----------+--------+-------+
| id | product_number | product_type | location | status | price |
+------+----------------+--------------+----------+--------+-------+
| 1 | A-01 | A001 | Nevada | READY | 5000 |
| 2 | B-02 | A002 | Texas | STORED | 6000 |
| 3 | A-01 | A002 | Utah | READY | 6000 |
| 4 | A-02 | B003 | Utah | READY | 8000 |
| 5 | B-01 | A001 | Nevada | STORED | 5000 |
+------+----------------+--------------+----------+--------+-------+
id is the primary key.
Supervisor
+------+-------+--------------+----------+-----------+--------+
| id | month | product_type | location | unit_sold | income |
+------+-------+--------------+----------+-----------+--------+
| 1 | 1 | A001 | Nevada | 5 | 25000 |
| 2 | 3 | A002 | Texas | 6 | 36000 |
| 3 | 1 | A002 | Utah | NULL | NULL |
| 4 | 4 | B003 | Utah | 4 | 32000 |
| 5 | 2 | A001 | Nevada | 6 | 30000 |
+------+-------+--------------+----------+-----------+--------+
I was asked that the result should be like this table (this is actually my estimation) :
SalesTarget table
Location : Nevada
+------+----------------+--------+--------+---------------+---------------+
| | STATUS | TOTAL | 1st MONTH | 2nd MONTH |
| TYPE | READY | STORED | UNIT | PRICE | UNIT | INCOME | UNIT | INCOME |
+------+-------+--------+--------+--------+------+--------+------+--------+
| A001 | 6 | 8 | 14 | 70000 | 5 | 25000 | 6 | 30000 |
| A002 | 7 | 4 | 11 | 66000 | 3 | 39000 | 0 | 0 |
| B001 | 3 | 6 | 19 | 95000 | 0 | 0 | 0 | 0 |
| B002 | 5 | 5 | 10 | 100000 | 4 | 40000 | 6 | 60000 |
+------+-------+--------+--------+--------+------+--------+------+--------+
The table only shows data only from specific location. STATUS READY is a cumulative from unit that has the same type and location which has READY state and so for STATUS STORED. TOTAL is total unit / price of the same type in that Location.
Unit and income in SalesTarget table can be NULL and it will be entered by the user, but they are classified by Supervisor.month (and also, it's for 12th month).
I join both table (ProductList and Supervisor) by product_type.
I tried using prepared statement query command like this, but it didn't give my exact result that I want.
SELECT
pl.product_type AS TYPE,
SUM(IF(pl.status = ? , 1, 0)) AS READY,
SUM(IF(pl.status = ? , 1, 0)) AS STORED,
SUM((IF((pl.status = ? OR pl.status = ? ), 1, 0))) AS UNIT_TOTAL,
SUM((IF((pl.status = ? OR pl.status = ? ), pl.price, 0))) AS PRICE_TOTAL,
IF(sv.month=1, sv.unit_sold, 0) AS UNIT1,
IF(sv.month=1, sv.income, 0) AS INCOME1,
IF(sv.month=2, sv.unit_sold, 0) AS UNIT2,
IF(sv.month=2, sv.income, 0) AS INCOME2
FROM ProductList pl
LEFT OUTER JOIN Supervisor sv ON pl.product_type = sv.product_type
WHERE pl.location = ?
GROUP BY pl.product_type
ORDER BY TYPE DESC
How can I do this?