Я пытаюсь создать 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 ;
Поделитесь существующим предложением выбора. – mseifert
Этот вопрос не так сформулирован. В какой логике говорится, что «23» должны войти в запись «Семья», а «15» - в запись «Друг». Я согласен с @mseifert, вы должны поделиться своей исходной схемой. Кроме того, NULL не является счетчиком, поэтому данные не соответствуют вашему описанию. – cliffordheath
Я добавил sp, который я использую. И технически нет логики для того, чтобы соответствовать «семье». Он просто удаляет все значения выше, которые имеют счет NULL. Кроме того, NULL - это абсолютно счет ... поэтому я не уверен, что вы имеете в виду. Например, с помощью Col2: то, что он сообщает, - это значение NULL отображается в этом поле 23 раза. – user3998848