2015-10-09 2 views
0

Я пытаюсь создать sp, который профилирует данные в таблице, получая подсчеты для каждого значения в каждом поле. Проблема, с которой я сталкиваюсь, заключается в том, что она создает таблицу профилей, делая серию союзов. Мои текущие результаты выглядят как Результат 1 ниже.MYSQL удаление нулей из каждого столбца

Мой вопрос: Есть ли предложение выбора, которое я могу использовать, чтобы результаты выглядели как Результат 2 или, возможно, лучший способ построить таблицу вместо использования союзов?

Результат 1

Col1  Col1_cnt Col2 Col2_cnt Col3 Col3_cnt 
Family  15  <NULL> <NULL>  <NULL> <NULL> 
Friend  4  <NULL> <NULL>  <NULL> <NULL> 
Coworker 3  <NULL> <NULL>  <NULL> <NULL> 
<NULL> <NULL> <NULL> 23  <NULL> <NULL> 
<NULL> <NULL> John  15  <NULL> <NULL> 
<NULL> <NULL> Jane  4  <NULL> <NULL> 
<NULL> <NULL> <NULL> <NULL>  <NULL>  8 
<NULL> <NULL> <NULL> <NULL>  Work  3 
<NULL> <NULL> <NULL> <NULL>  School  2 
<NULL> <NULL> <NULL> <NULL>  Social  1 
<NULL> <NULL> <NULL> <NULL>  Conf  5 

Желаемая Результат 2

Col1 Col1_cnt Col2 Col2_cnt Col3 Col3_cnt 
Family 15  <NULL> 23  <NULL> 8 
Friend  4  John  15  Work  3 
Coworker 3  Jane  4  School 2 
<NULL> <NULL>  <NULL> <NULL>  Social 1 
<NULL> <NULL>  <NULL> <NULL>  Conf  5 

Вот зр я создал:

DROP PROCEDURE IF EXISTS my_db.usp_profile_data; 
DELIMITER $$ 
CREATE PROCEDURE my_db.usp_profile_data(IN vdb_name VARCHAR(255), IN vtbl_name VARCHAR(255)) 

BEGIN 
#CREATES TEMP TABLE TO HOUSE SCHEMA DATA 
DROP TABLE IF EXISTS my_db.profile_data; 
CREATE TEMPORARY TABLE my_db.profile_data 
(id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, 
    #ord_position INT, 
    col_name VARCHAR(255), 
    col_type VARCHAR(255)); 

#INSERTS COLUMNS OF DB AND TABLE PASSED EXCLUDING SYS FIELDS 
INSERT INTO my_db.profile_data(col_name, col_type) 
SELECT COLUMN_NAME, 
    COLUMN_TYPE 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_schema = vdb_name 
AND table_name = vtbl_name 
AND EXTRA <> ('auto_increment') 
AND COLUMN_NAME NOT IN('update_dt','credate_dt'); 

#DROP PROFILE TABLE IF ALREADY EXISTS 
DROP TABLE IF EXISTS my_db.profile_data_FIN; 

#INITIALIZES LOOP VARIABLE 
SELECT COUNT(*) 
FROM my_db.profile_data 
INTO @vLoop; 

#INITIALIZE INCREMENT VARIABLE 
SET @vInc =1; 

#BEGIN LOOP THROUGH FIELDS 
WHILE @vInc <= (@vLoop) DO 


    #STORES COLUMN NAME AND DATA TYPE TO BE USED IN CREATING THE PROFILE TABLE 
    SELECT col_name, 
       col_type 
    FROM my_db.profile_data 
    WHERE id = @vInc 
    INTO @vColName,@vColType; 

    #IF FIRST PASS CREATE THE TABLE, ELSE ADD COLUMNS 
    IF (@vInc = 1) THEN 
     SET @vSQL_Tbl = CONCAT('CREATE TEMPORARY TABLE my_db.profile_data_FIN (',@vColName,' ',@vColType,', cnt_',@vColName,' INT)'); 
    ELSE 
     SET @vSQL_Tbl = CONCAT('ALTER TABLE my_db.profile_data_FIN ADD COLUMN ',@vColName,' ',@vColType,', ADD COLUMN cnt_',@vColName,' INT'); 
    END IF; 

    #EXECUTES THE DYNAMIC TABLE STATEMENT 
    PREPARE stmtTbl FROM @vSQL_Tbl; 

     EXECUTE stmtTbl; 

    DEALLOCATE PREPARE stmtTbl; 

    #CREATES SQL QUERY USED TO POPULATE THE PROFILE TABLE 
    SET @vSQL = CONCAT('INSERT INTO my_db.profile_data_FIN (', @vColName,', cnt_',@vColName,')', 'SELECT ',@vColName,', COUNT(*) AS cnt_',@vColName,' FROM ',vdb_name ,'.', vtbl_name,' GROUP BY ', @vColName, ' ORDER BY 2 DESC'); 

    #EXECUTES THE POPULATION OF THE PROFILE TABLE 
    PREPARE stmtQry FROM @vSQL; 

     EXECUTE stmtQry; 

    DEALLOCATE PREPARE stmtQry; 

    #SELECT @vSQL; 

    SET @vInc [email protected]+1; 

END WHILE; 


SELECT * 
FROM my_db.profile_data_FIN; 

END$$ 
DELIMITER ; 
+0

Поделитесь существующим предложением выбора. – mseifert

+0

Этот вопрос не так сформулирован. В какой логике говорится, что «23» должны войти в запись «Семья», а «15» - в запись «Друг». Я согласен с @mseifert, вы должны поделиться своей исходной схемой. Кроме того, NULL не является счетчиком, поэтому данные не соответствуют вашему описанию. – cliffordheath

+0

Я добавил sp, который я использую. И технически нет логики для того, чтобы соответствовать «семье». Он просто удаляет все значения выше, которые имеют счет NULL. Кроме того, NULL - это абсолютно счет ... поэтому я не уверен, что вы имеете в виду. Например, с помощью Col2: то, что он сообщает, - это значение NULL отображается в этом поле 23 раза. – user3998848

ответ

1

Попробуйте ниже query-

Вы можете проверить sqlfiddle он число рейнольдса

SELECT a.s_no,a.col1,a.col1_cnt,b.col2,b.col2_cnt,c.col3,c.col3_cnt FROM 
(SELECT a.s_no,b.col1,b.col1_cnt FROM (SELECT 1 AS s_no UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) a LEFT JOIN (SELECT @n := @n + 1 AS s_no1,col1,col1_cnt FROM mytable a JOIN (SELECT @n := 0) m WHERE col1_cnt IS NOT NULL) b ON a.s_no=b.s_no1) a 
LEFT JOIN (SELECT @n2 := @n2 + 1 AS s_no,col2,col2_cnt FROM mytable a JOIN (SELECT @n2 := 0) m2 WHERE col2_cnt IS NOT NULL) b 
ON a.s_no=b.s_no 
LEFT JOIN (SELECT @n3 := @n3 + 1 AS s_no,col3,col3_cnt FROM mytable a JOIN (SELECT @n3 := 0) m3 WHERE col3_cnt IS NOT NULL) c 
ON a.s_no=c.s_no 
where c.col3_cnt is not null 
ORDER BY a.s_no; 
+0

Впечатляющий Zafar, я смог повторно запустить ваш код из sqlfiddle, и он сработал! В настоящее время я получаю сообщение об ошибке: «Код ошибки: 1137. Не удается открыть таблицу:« a », когда я изменяю ее, чтобы соответствовать моим db и таблице. Мысли? Возможно ли это, потому что мой sp создает временную таблицу? – user3998848

+0

И временная таблица - это точно проблема. Еще раз спасибо. https://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html – user3998848

Смежные вопросы