How to get rid of null values in pivoted table? - mysql

I am trying to pivot a table in MySQL so that I can turn row values into column headers for an easier-to-read table in a report. Here is a sample of what comes out so far (data has been obfuscated a bit but the concept is still the same):
+------------+------+------+---------+
| Date | RS1 | RS2 | RS3 |
+------------+------+------+---------+
| 2007-02-26 | 12 | NULL | NULL |
| 2007-04-12 | 8 | NULL | NULL |
| 2007-07-31 | 9 | NULL | NULL |
| 2008-02-07 | 12 | NULL | NULL |
| 2008-11-06 | 20 | NULL | NULL |
| 2010-03-04 | 8 | NULL | NULL |
| 2010-12-16 | 7 | NULL | NULL |
| 2011-01-24 | 20 | NULL | NULL |
| 2011-03-22 | 7 | NULL | NULL |
| 2012-11-12 | 19 | NULL | NULL |
| 2007-02-26 | NULL | 18 | NULL |
| 2007-04-12 | NULL | 2 | NULL |
| 2007-07-31 | NULL | 4 | NULL |
| 2008-02-07 | NULL | 10 | NULL |
| 2008-11-06 | NULL | 8 | NULL |
| 2010-03-04 | NULL | 6 | NULL |
| 2010-12-16 | NULL | 6 | NULL |
| 2011-01-24 | NULL | 5 | NULL |
| 2011-03-22 | NULL | 11 | NULL |
| 2012-11-12 | NULL | 13 | NULL |
| 2007-02-26 | NULL | NULL | 15 |
| 2007-04-12 | NULL | NULL | 6 |
| 2007-07-31 | NULL | NULL | 5 |
| 2008-02-07 | NULL | NULL | 8 |
| 2008-11-06 | NULL | NULL | 11 |
| 2010-03-04 | NULL | NULL | 1 |
| 2010-12-16 | NULL | NULL | 19 |
| 2011-01-24 | NULL | NULL | 14 |
| 2011-03-22 | NULL | NULL | 15 |
| 2012-11-12 | NULL | NULL | 10 |
+------------+------+------+---------+
30 rows in set (0.00 sec)
The only thing left to do is to get rid of the NULL values so that all the columns are aligned with each other for each date. In other words, delete the last 20 rows from column 1, the first 10 and last 10 from column 2, and the first 20 from column 3, so that all the columns and their values are aligned.
Is there an easy way to do this in MySQL?

Try this:
SELECT Date,
MAX(RS1),
MAX(RS2),
MAX(RS3)
FROM Table1
GROUP BY Date
SQLFiddle demo

You can create a new table and INSERT again the data while grouping by date:
INSERT INTO mynewtable (date,RS1,RS2,RS3)
SELECT Date,MAX(RS1),MAX(RS2),MAX(RS3)
FROM myoldtable GROUP BY Date

Related

fill at once data null on table sql

I have table transaksi:
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(150) | YES | | NULL | |
| price | int(11) | YES | | NULL | |
| type | int(11) | YES | | NULL | |
+-------------+--------------+------+-----+---------+-------+
and have data (I fill in the data with insert into transaksi (name,price,type) select name,price,type from store)
+-----------+--------------------------+---------+-------+
| id | name | price | Type |
+-----------+--------------------------+---------+-------+
| NULL | Pants | 79 | 9 |
| NULL | Cup | 38 | 7 |
| NULL | Shoes | 21 | 1 |
| NULL | Hat | 11 | 5 |
| NULL | Pulpen | 39 | 2 |
+___________|__________________________|_________|_______|
How to fill "NULL" data at once in ID ?

While display group of table value in mysql it shows each and every value as '0'

my table
mysql> desc attendance;
+--------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------+------+-----+---------+----------------+
| aid | bigint(20) | NO | PRI | NULL | auto_increment |
| sid | int(10) | YES | MUL | NULL | |
| cid | bigint(20) | YES | MUL | NULL | |
| ttid | bigint(20) | YES | MUL | NULL | |
| did | int(3) | YES | MUL | NULL | |
| date | date | YES | | NULL | |
| hour | varchar(3) | YES | | NULL | |
| stuid | bigint(20) | YES | MUL | NULL | |
| status | varchar(8) | YES | | NULL | |
+--------+------------+------+-----+---------+----------------+
9 rows in set (0.47 sec)
and it's values are
mysql> select * from attendance;
+-----+------+------+------+------+------------+------+-------+---------+
| aid | sid | cid | ttid | did | date | hour | stuid | status |
+-----+------+------+------+------+------------+------+-------+---------+
| 1 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 16 | present |
| 2 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 17 | absent |
| 3 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 18 | present |
| 4 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 19 | absent |
| 5 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 20 | present |
| 6 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 15 | absent |
| 7 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 16 | present |
| 8 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 17 | absent |
| 9 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 18 | present |
| 10 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 19 | absent |
| 11 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 20 | present |
| 12 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 15 | absent |
| 13 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 16 | present |
| 14 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 17 | present |
| 15 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 18 | present |
| 16 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 19 | present |
| 17 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 20 | present |
| 18 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 15 | present |
| 19 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 16 | absent |
| 20 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 17 | absent |
| 21 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 18 | present |
| 22 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 19 | present |
| 23 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 20 | present |
| 24 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 15 | absent |
+-----+------+------+------+------+------------+------+-------+---------+
24 rows in set (0.00 sec)
Now, i am going to grouping table but returns value in 0
While group the table it returns each and every column value returns in 0.
Why that is happened. I need present or absent instead of 0.
Can anyone solve this logic error?
sum(case when hour = 'P1' then status else 'null' end) p1
The problem is that you are suming numbers and litteral string 'null'.
You wanted null (without quotes) - or better yet, 0
sum(case when hour = 'p1' then status else 0 end) p1
Note that in MySQL evaluates true/false conditions as 1/0 in numeric context, which allows shortening the expression like:
sum(hour = 'p1') p1
create view attendance1 as(
select attendance.stuid,
case when hour="p1" then status end as p1,
case when hour="p2" then status end as p2,
case when hour="p3" then status end as p3,
case when hour="p4" then status end as p4,
case when hour="p5" then status end as p5,
case when hour="p6" then status end as p6,
case when hour="p7" then status end as p7,
case when hour="p8" then status end as p8
from attendance);
select * from attendance1;
mysql> select * from attendance1;
+-----+------+------+------+------+------------+------+-------+---------+---------+---------+------+------+------+---------+------+---------+
| aid | sid | cid | ttid | did | date | hour | stuid | status | p1 | p2 | p3 | p4 | p5 | p6 | p7 | p8 |
+-----+------+------+------+------+------------+------+-------+---------+---------+---------+------+------+------+---------+------+---------+
| 1 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 16 | present | present | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 17 | absent | absent | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 3 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 18 | present | present | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 4 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 19 | absent | absent | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 5 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 20 | present | present | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 6 | 2 | 13 | 4 | 3 | 2020-03-25 | p1 | 15 | absent | absent | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 7 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 16 | present | NULL | NULL | NULL | NULL | NULL | present | NULL | NULL |
| 8 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 17 | absent | NULL | NULL | NULL | NULL | NULL | absent | NULL | NULL |
| 9 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 18 | present | NULL | NULL | NULL | NULL | NULL | present | NULL | NULL |
| 10 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 19 | absent | NULL | NULL | NULL | NULL | NULL | absent | NULL | NULL |
| 11 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 20 | present | NULL | NULL | NULL | NULL | NULL | present | NULL | NULL |
| 12 | 2 | 13 | 2 | 2 | 2020-03-17 | p6 | 15 | absent | NULL | NULL | NULL | NULL | NULL | absent | NULL | NULL |
| 13 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 16 | present | NULL | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 14 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 17 | present | NULL | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 15 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 18 | present | NULL | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 16 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 19 | present | NULL | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 17 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 20 | present | NULL | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 18 | 2 | 13 | 4 | 3 | 2020-03-25 | p2 | 15 | present | NULL | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 19 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 16 | absent | NULL | NULL | NULL | NULL | NULL | NULL | NULL | absent |
| 20 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 17 | absent | NULL | NULL | NULL | NULL | NULL | NULL | NULL | absent |
| 21 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 18 | present | NULL | NULL | NULL | NULL | NULL | NULL | NULL | present |
| 22 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 19 | present | NULL | NULL | NULL | NULL | NULL | NULL | NULL | present |
| 23 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 20 | present | NULL | NULL | NULL | NULL | NULL | NULL | NULL | present |
| 24 | 2 | 13 | 4 | 3 | 2020-03-25 | p8 | 15 | absent | NULL | NULL | NULL | NULL | NULL | NULL | NULL | absent |
+-----+------+------+------+------+------------+------+-------+---------+---------+---------+------+------+------+---------+------+---------+
24 rows in set (0.02 sec)
Finally I found solution based on previous mistakes
create view attendance1 as(
select attendance.*,
case when hour="p1" then status end as p1,
case when hour="p2" then status end as p2,
case when hour="p3" then status end as p3,
case when hour="p4" then status end as p4,
case when hour="p5" then status end as p5,
case when hour="p6" then status end as p6,
case when hour="p7" then status end as p7,
case when hour="p8" then status end as p8
from attendance);
mysql> select * from attendance1;
+------+------+------+------+------------+------+-------+---------+---------+---------+------+------+------+------+------+------+
| sid | cid | ttid | did | date | hour | stuid | status | p1 | p2 | p3 | p4 | p5 | p6 | p7 | p8 |
+------+------+------+------+------------+------+-------+---------+---------+---------+------+------+------+------+------+------+
| 2 | 13 | 4 | 3 | 2020-04-22 | p1 | 16 | present | present | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p1 | 17 | absent | absent | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p1 | 18 | present | present | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p1 | 19 | absent | absent | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p1 | 20 | present | present | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p1 | 15 | absent | absent | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p2 | 16 | absent | NULL | absent | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p2 | 17 | present | NULL | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p2 | 18 | absent | NULL | absent | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p2 | 19 | present | NULL | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p2 | 20 | absent | NULL | absent | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 13 | 4 | 3 | 2020-04-22 | p2 | 15 | present | NULL | present | NULL | NULL | NULL | NULL | NULL | NULL |
+------+------+------+------+------------+------+-------+---------+---------+---------+------+------+------+------+------+------+
12 rows in set (0.00 sec)
Based on first view i'll create second view
mysql>
create view attendance2 as(
select stuid,
max(p1)as p1,
max(p2)as p2,
max(p3)as p3,
max(p4)as p4,
max(p5)as p5,
max(p6)as p6,
max(p7)as p7,
max(p8)as p8
from attendance1
group by stuid);
mysql> select * from attendance2;
+-------+---------+---------+------+------+------+------+------+------+
| stuid | p1 | p2 | p3 | p4 | p5 | p6 | p7 | p8 |
+-------+---------+---------+------+------+------+------+------+------+
| 15 | absent | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 16 | present | absent | NULL | NULL | NULL | NULL | NULL | NULL |
| 17 | absent | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 18 | present | absent | NULL | NULL | NULL | NULL | NULL | NULL |
| 19 | absent | present | NULL | NULL | NULL | NULL | NULL | NULL |
| 20 | present | absent | NULL | NULL | NULL | NULL | NULL | NULL |
+-------+---------+---------+------+------+------+------+------+------+
6 rows in set (0.00 sec)
Thanks for previous questions answered person.

Update a date column with the result of the next closest date column

I have a MySQL table that looks like this:
+-------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+-------+
| person_id | int(11) | NO | MUL | NULL | |
| location_id | int(11) | NO | MUL | NULL | |
| date_signed | date | NO | | NULL | |
| date_ended | date | YES | | NULL | |
+-------------+---------+------+-----+---------+-------+
Where all of the records are like this:
+-----------+-------------+-------------+------------+
| person_id | location_id | date_signed | date_ended |
+-----------+-------------+-------------+------------+
| 1 | 49 | 2007-09-29 | NULL |
| 1 | 41 | 2010-10-09 | NULL |
| 2 | 45 | 2007-09-29 | NULL |
| 2 | 58 | 2007-12-16 | NULL |
| 3 | 49 | 2007-09-29 | NULL |
| 4 | 45 | 2007-09-29 | NULL |
| 4 | 35 | 2013-10-04 | NULL |
| 5 | 45 | 2007-09-29 | NULL |
| 5 | 37 | 2009-01-09 | NULL |
| 5 | 32 | 2009-10-08 | NULL |
+-----------+-------------+-------------+------------+
I'm trying to update each person's date_ended to be one day less than the date_signed in the next chronological row for that person:
+-----------+-------------+-------------+------------+
| person_id | location_id | date_signed | date_ended |
+-----------+-------------+-------------+------------+
| 1 | 49 | 2007-09-29 | 2010-10-08 |
| 1 | 41 | 2010-10-09 | NULL |
| 2 | 45 | 2007-09-29 | 2007-12-15 |
| 2 | 58 | 2007-12-16 | NULL |
.
.
.
But I can't figure out how to select the next chronological record. I tried a few suggestions from similar questions:
UPDATE a column based on the value of another column in the same table
Mysql - update table column from another column based on order
ROW_NUMBER() in MySQL
But I couldn't get them to work. Is there a way to do this in MySQL?
SQL Fiddle: http://sqlfiddle.com/#!9/8b5219/1

Insert value in a table

I have a question about inserting row in an table which is already created.
This is my table :
mysql> describe llx_document_model ;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| rowid | int(11) | NO | PRI | NULL | auto_increment |
| nom | varchar(50) | YES | MUL | NULL | |
| entity | int(11) | NO | | 1 | |
| type | varchar(20) | NO | | NULL | |
| libelle | varchar(255) | YES | | NULL | |
| description | text | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
If I print the table :
mysql> select * from llx_document_model ;
+-------+----------+--------+-------------------+---------+-------------+
| rowid | nom | entity | type | libelle | description |
+-------+----------+--------+-------------------+---------+-------------+
| 1 | standard | 1 | deplacement | NULL | NULL |
| 7 | soleil | 1 | ficheinter | NULL | NULL |
| 13 | rouget | 1 | shipping | NULL | NULL |
| 14 | typhon | 1 | delivery | NULL | NULL |
| 16 | aurore | 1 | supplier_proposal | NULL | NULL |
| 17 | muscadet | 1 | order_supplier | NULL | NULL |
| 18 | baleine | 1 | project | NULL | NULL |
| 19 | einstein | 1 | order | NULL | NULL |
| 21 | azur | 1 | propal | NULL | NULL |
| 23 | strato | 1 | contract | strato | NULL |
| 32 | crabe | 1 | invoice | crabe | NULL |
+-------+----------+--------+-------------------+---------+-------------+
11 rows in set (0.00 sec)
I want to add a row, so I write :
mysql> INSERT INTO llx_document_model
-> VALUES(NULL, moriba, 1, invoice, moriba, NULL);
But I get this error :
ERROR 1054 (42S22): Unknown column 'moriba' in 'field list'
Do you have some idea about my problem ? I don't see really where I made an error.
Thank you by advance !
string should be enclosed by (')single quotes
mysql> INSERT INTO llx_document_model VALUES(NULL, 'moriba', 1, 'invoice', 'moriba', NULL);

Adding (results of a query) to an existing table

So i have the following problem. I have 2 tables (Users: 100 rows and geo-zipcodes: 450k rows) and I want to update my users table to display the lon and lat if the zipcode is filled in. When it's not filled in i want the lon/lat to display NULL. How do I achieve this?
I do this in MySQL using the standard provided MySQL workbench.
+CURRENT SITUATION----+------+
| id | zipcode | lon | lat |
+----+---------+------+------+
| 88 | 3531EK | NULL | NULL |
| 89 | 5691JN | NULL | NULL |
| 90 | 5701NR | NULL | NULL |
| 91 | 3531EK | NULL | NULL |
| 92 | 5691JN | NULL | NULL |
| 93 | NULL | NULL | NULL |
| 94 | NULL | NULL | NULL |
| 95 | NULL | NULL | NULL |
| 96 | NULL | NULL | NULL |
| 97 | NULL | NULL | NULL |
+----+---------+------+------+
+FUTURE SITUATION------------------+-----------------+
| id | zipcode | lat | lon |
+-----+---------+------------------+-----------------+
| 583 | NULL | NULL | NULL |
| 632 | NULL | NULL | NULL |
| 797 | 4194WD | 51.8724978062918 | 5.2758839816285 |
| 812 | 9723ZT | 53.2067353295688 | 6.5886266741127 |
| 782 | 5617BD | 51.4471593854488 | 5.4566869544855 |
| 799 | NULL | NULL | NULL |
| 800 | 5623ET | 51.4618395108795 | 5.4733910341403 |
| 179 | 5709BN | 51.4752182995384 | 5.7022349534995 |
| 112 | 5701CN | 51.4759330063412 | 5.6780783810570 |
| 90 | 5701NR | 51.4775509176254 | 5.6576320175919 |
+-----+---------+------------------+-----------------+
In MySQL, you can do this with a join:
update users u join
zipcodes z
on u.zipcode = z.zipcode
set u.lat = z.lat, u.lon = z.lon;
However, I don't see why this is necessary. Why not just look up the coordinates using the zip code table when you need it? There might be good reasons -- for instance, you might have other sources of coordinates. But if the zip code is the only source, then there is no need to store the same information in two places.