简体   繁体   中英

How to get MYSQL information schema column names with filled out count?

I tried to get all column names of specific table from information schema in MYSQL and I did it very well.

Now I want to append the count of filled out(the column should not be null) of each column in front of their name.

Here is my query:

SELECT column_name
FROM information_schema.columns
WHERE table_schema = 'hr_db'
AND table_name = "employee_tbl"

The above query result is:

COLUMN_NAME
+-----------
id
------------
name
------------
phone
------------
email

But what I want is like below:

COLUMN_NAME   COUNT
+------------------
id            20
-------------------
name          20
-------------------
phone         12
-------------------
email         5

Thanks in advance for your comments and answers

It's relatively easy using prepared statements to get one row of totals for example

set @sql = (
concat('select ',
(
select group_concat(concat('count(',column_name,') as ',column_name)) 
from information_schema.columns
where table_name = 'users' and table_schema = 'sandbox'
)
, ' from users')
);

prepare sqlstmt from @sql;
execute sqlstmt;
deallocate prepare sqlstmt;

+----+------+----------+-------+-----------+----------+-----+-----+------------+----+
| id | name | password | email | firstname | lastname | sal | age | event_date | ts |
+----+------+----------+-------+-----------+----------+-----+-----+------------+----+
|  6 |    3 |        2 |     0 |         1 |        3 |   2 |   0 |          4 |  6 |
+----+------+----------+-------+-----------+----------+-----+-----+------------+----+
1 row in set (0.00 sec)

If you want 1 row per column then because mysql does not have an unpivot funtion you could

drop procedure if exists p;
delimiter $$
create procedure p(inschema varchar(100), intable varchar(100))
begin

declare cname varchar(100);
declare done int default false;

DECLARE cur CURSOR FOR
        SELECT column_name from information_schema.columns
        where table_schema = inschema and table_name = intable
          order by ordinal_position;

DECLARE CONTINUE handler FOR NOT FOUND SET done = TRUE;

    OPEN cur;
    set @sql = '';
    LOOP1: LOOP
        #set no_more_rows1 = false;
        FETCH cur INTO cname;
        IF done THEN
            CLOSE cur;
            LEAVE LOOP1;
        END IF;

        set @sql = concat(@sql, 'select ', char(39),cname,char(39), ', count(', cname, ') as count from ' , intable, ' union ');

    END LOOP LOOP1; 
     set @sql = concat(substring(@sql,1,length(@sql) - 7),';');    
    prepare sqlstmt from @sql;
    execute sqlstmt;
    deallocate prepare sqlstmt;
end $$
delimiter ;


call p('sandbox','users');
+------------+-------+
| id         | count |
+------------+-------+
| id         |     6 |
| name       |     3 |
| password   |     2 |
| email      |     0 |
| firstname  |     1 |
| lastname   |     3 |
| sal        |     2 |
| age        |     0 |
| event_date |     4 |
| ts         |     6 |
+------------+-------+
10 rows in set (0.03 sec)

Or if you don't like a procedure then something like this

set @sql = 
(
select group_concat(concat('select ' ,char(39),column_name,char(39), ',count(' , column_name, ') from users union ' ))
from information_schema.`COLUMNS` where table_schema = 'sandbox' and table_name = 'users'
);

set @sql = replace(@sql,'union ,','union ');

set @sql = concat(substring(@sql,1,length(@sql) - 7),';'); 
prepare sqlstmt from @sql;
execute sqlstmt;
deallocate prepare sqlstmt;

您可以通过常规选择来实现:

SELECT COUNT(`id`), COUNT(`name`), COUNT(`phone`), COUNT(`email`) FROM `employee_tbl`;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM