MySQL Query for averages - mysql

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;

Related

Pivoting in MySQL converting rows into columns

I have the following dataset and i would like to convert rows into columns
+----------+---------+
| assoc | player |
+----------+---------+
| 1 | 12 |
| 1 | 20 |
| 1 | 30 |
| 2 | 51 |
| 2 | 52 |
| 2 | 63 |
+----------+---------+
Making the view looks like
+----------+----------+----------+----------+
| assoc | player1 | player2 | player3 |
+----------+----------+----------+----------+
| 1 | 12 | 20 | 30 |
| 2 | 51 | 52 | 63 | |
+----------+----------+----------+----------+

Query the differences between records with same ID

I have a table like this in MS Access 2019:
+-----------+------------+--------+----------+-------+
| BillingID | Date | RoomID | Electric | Water |
+-----------+------------+--------+----------+-------+
| 1 | 12/23/2018 | 4 | 1669 | 106 |
| 2 | 12/26/2018 | 1 | 5035 | 289 |
| 3 | 12/27/2018 | 6 | 0 | 0 |
| 4 | 12/31/2018 | 5 | 3158 | 223 |
| 5 | 1/6/2019 | 2 | 3823 | 194 |
| 6 | 1/15/2019 | 3 | 1772 | 125 |
| 7 | 1/23/2019 | 4 | 1796 | 117 |
| 8 | 1/26/2019 | 1 | 5231 | 299 |
| 9 | 1/27/2019 | 6 | 0 | 0 |
| 10 | 1/31/2019 | 5 | 3366 | 242 |
| 11 | 2/14/2019 | 2 | 3975 | 201 |
| 12 | 2/15/2019 | 3 | 1839 | 129 |
+-----------+------------+--------+----------+-------+
I could calculate the electricity and water usage with Index & Match in MS Excel. However, I've had a lot of trouble to achieve this with MS Access. The result I want is as below:
+-----------+------------+--------+----------+---------------+-------+------------+
| BillingID | Date | RoomID | Electric | ElectricUsage | Water | WaterUsage |
+-----------+------------+--------+----------+---------------+-------+------------+
| 1 | 12/23/2018 | 4 | 1669 | | 106 | |
| 2 | 12/26/2018 | 1 | 5035 | | 289 | |
| 3 | 12/27/2018 | 6 | 0 | | 0 | |
| 4 | 12/31/2018 | 5 | 3158 | | 223 | |
| 5 | 1/6/2019 | 2 | 3823 | | 194 | |
| 6 | 1/15/2019 | 3 | 1772 | | 125 | |
| 7 | 1/23/2019 | 4 | 1796 | 127 | 117 | 11 |
| 8 | 1/26/2019 | 1 | 5231 | 196 | 299 | 10 |
| 9 | 1/27/2019 | 6 | 0 | | 0 | |
| 10 | 1/31/2019 | 5 | 3366 | 208 | 242 | 19 |
| 11 | 2/14/2019 | 2 | 3975 | 152 | 201 | 7 |
| 12 | 2/15/2019 | 3 | 1839 | 67 | 129 | 4 |
+-----------+------------+--------+----------+---------------+-------+------------+
For example, for RoomID = 4, the ElectricUsage is the difference between the Electric in BillingID #7 and BillingID #1 and so on.
I've tried some answer like this or this but Access ran into errors when using those solutions in SQL view (Syntax error in FROM clause).
Thanks.
You can use a couple of sub-queries to return the Electric/Water for each room on the previous date:
SELECT
B.BillingID, B.BillingDate, B.RoomID, B.Electric,
B.Electric-(SELECT TOP 1 E.Electric FROM tblBilling AS E WHERE B.RoomID=E.RoomID AND E.BillingDate<B.BillingDate ORDER BY E.BillingDate DESC) AS ElectricUsage,
B.Water,
B.Water-(SELECT TOP 1 W.Water FROM tblBilling AS W WHERE B.RoomID=W.RoomID AND W.BillingDate<B.BillingDate ORDER BY W.BillingDate DESC) AS WaterUsage
FROM tblBilling AS B
Note that I've renamed your Date field to be BillingDate, as Date is a reserved word in Access, and will cause you problems in the future.
Regards,

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

Picking out specific values from a group in MySQL

This seems like such a simple problem, but I can't find a good solution. I'm trying to select information from a slightly misformatted table. Basically, wherever sequence=0, the person_id should actually be a company_id. This company_id then applies to all the rows which have the same group_id.
Someone thought it was a good idea to format things this way instead of simply having a company_id column, but it makes trying to select by company very difficult. It would make my programming much easier to simply add this extra column, and fix the formatting.
I want to turn something like this:
+----------+------------+-----------+----------+
| group_id | date | person_id | sequence |
+----------+------------+-----------+----------+
| 1 | 2012-08-31 | 10 | 0 |
| 1 | 2012-08-31 | 11 | 1 |
| 1 | 2012-08-31 | 12 | 2 |
| 2 | 1999-04-16 | 10 | 0 |
| 2 | 1999-04-16 | 21 | 1 |
| 2 | 1999-04-16 | 22 | 2 |
| 2 | 1999-04-16 | 23 | 3 |
| 2 | 1999-04-16 | 24 | 4 |
| 3 | 2001-01-09 | 30 | 0 |
| 3 | 2001-01-09 | 31 | 1 |
| 3 | 2001-01-09 | 11 | 2 |
| 3 | 2001-01-09 | 12 | 3 |
+----------+------------+-----------+----------+
Into this:
+------------+----------+------------+-----------+----------+
| company_id | group_id | date | person_id | sequence |
+------------+----------+------------+-----------+----------+
| 10 | 1 | 2012-08-31 | 11 | 1 |
| 10 | 1 | 2012-08-31 | 12 | 2 |
| 10 | 2 | 1999-04-16 | 21 | 1 |
| 10 | 2 | 1999-04-16 | 22 | 2 |
| 10 | 2 | 1999-04-16 | 23 | 3 |
| 10 | 2 | 1999-04-16 | 24 | 4 |
| 30 | 3 | 2001-01-09 | 31 | 1 |
| 30 | 3 | 2001-01-09 | 11 | 2 |
| 30 | 3 | 2001-01-09 | 12 | 3 |
+------------+----------+------------+-----------+----------+
The only way I can think of how to achieve this is with nested SELECT statements, which are very inefficient considering I have about 100M rows. It's a one time fix though, so I don't mind letting it run overnight.
If you permanently want to change your table to include a company_id column then do this:
First alter the table and add the new column:
alter table your_table add company_id int;
Then update all rows to set the company to the person_id = 0 for the group:
UPDATE your_table a
JOIN your_table b ON a.group_id = b.group_id
SET a.company_id = b.person_id
WHERE b.sequence = 0;
And finally remove the rows with sequence = 0:
DELETE FROM your_table WHERE sequence = 0;
Sample SQL Fiddle
The end result will be:
| group_id | date | person_id | sequence | company_id |
|----------|------------|-----------|----------|------------|
| 1 | 2012-08-31 | 11 | 1 | 10 |
| 1 | 2012-08-31 | 12 | 2 | 10 |
| 2 | 1999-04-16 | 21 | 1 | 10 |
| 2 | 1999-04-16 | 22 | 2 | 10 |
| 2 | 1999-04-16 | 23 | 3 | 10 |
| 2 | 1999-04-16 | 24 | 4 | 10 |
| 3 | 2001-01-09 | 31 | 1 | 30 |
| 3 | 2001-01-09 | 11 | 2 | 30 |
| 3 | 2001-01-09 | 12 | 3 | 30 |

How to duplicate row and generate not duplicate ID in mysql

I am using mysql and need to duplicate all row in my table but I do not duplicate id column and new generate number
need ex.
my table
item_db
+------------------------------------------+
| id | name | price | detail |
+------------------------------------------+
| 1 | example | 230 | 3 |
| 2 | power | 110 | 3 |
| 3 | voltage | 1.2 | 4 |
| 4 | example | 240 | 4 |
| 5 | example | 320 | 6 |
| 6 | power | 100 | 4 |
| 7 | power | 110 | 6 |
| 8 | example | 230 | 3 |
| 9 | power | 110 | 3 |
| 10 | voltage | 1.2 | 4 |
| 20 | example | 240 | 4 |
| 21 | example | 320 | 6 |
| 22 | power | 100 | 4 |
| 23 | power | 110 | 6 |
| 24 | example | 240 | 4 |
| 25 | example | 320 | 6 |
| 26 | power | 100 | 4 |
| 27 | power | 110 | 6 |
| 28 | example | 240 | 4 |
| 29 | example | 320 | 6 |
| 30 | power | 100 | 4 |
+------------------------------------------+
i need to duplicate
item_db
+------------------------------------------+
| id | name | price | detail |
+------------------------------------------+
| 1 | example | 230 | 3 |
| 2 | power | 110 | 3 |
| 3 | voltage | 1.2 | 4 |
| 4 | example | 240 | 4 | I need to dup id 1-10 to 101-110
| 5 | example | 320 | 6 |
| 6 | power | 100 | 4 |
| 7 | power | 110 | 6 |
| 8 | example | 230 | 3 |
| 9 | power | 110 | 3 |
| 10 | voltage | 1.2 | 4 |
| 101| example | 230 | 3 |
| 102| power | 110 | 3 |
| 103| voltage | 1.2 | 4 |
| 104| example | 240 | 4 |
| 105| example | 320 | 6 |
| 106| power | 100 | 4 |
| 107| power | 110 | 6 |
| 108| example | 230 | 3 |
| 109| power | 110 | 3 |
| 110| voltage | 1.2 | 4 |
| 20 | example | 240 | 4 |
| 21 | example | 320 | 6 |
| 22 | power | 100 | 4 |
| 23 | power | 110 | 6 |
| 24 | example | 240 | 4 |
| 25 | example | 320 | 6 |
| 26 | power | 100 | 4 | i need to dup 20-30 to 200-210
| 27 | power | 110 | 6 |
| 28 | example | 240 | 4 |
| 29 | example | 320 | 6 |
| 30 | power | 100 | 4 |
| 200| example | 240 | 4 |
| 201| example | 320 | 6 |
| 202| power | 100 | 4 |
| 203| power | 110 | 6 |
| 204| example | 240 | 4 |
| 205| example | 320 | 6 |
| 206| power | 100 | 4 |
| 207| power | 110 | 6 |
| 208| example | 240 | 4 |
| 209| example | 320 | 6 |
| 210| power | 100 | 4 |
+------------------------------------------+
thanks you expert.
You can use INSERT ... SELECT:
INSERT INTO item_db (id, name, price, detail)
SELECT id+180, name, price, detail FROM item_db WHERE id BETWEEN 20 AND 30
How exactly you want to treat id is not entirely clear. If, for example, you wish to automatically assign AUTO_INCREMENT values, then you can (as usual) omit it from the INSERT statement.