我正在尝试创建一个sp,它通过检索每个字段中每个值的计数来对表中的数据进行概要分析。我遇到的问题是它通过执行一系列联合来构建一个配置文件表。我目前的结果如下面的结果1。
我的问题是:我是否可以使用select语句使结果看起来像结果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
这是我创建的sp:
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 =@vInc+1;
END WHILE;
SELECT *
FROM my_db.profile_data_FIN;
END$$
DELIMITER ;
答案 0 :(得分:1)
尝试以下查询 -
您可以在此处查看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;