쿼리를 재현하는 데 필요한 데이터베이스의 하위 집합을 mysqldump 할 수 있습니까? 집합을 제공하고 싶습니다 . 저의 목표는 계산

배경

select쿼리 를 재현하는 데 필요한 데이터베이스의 하위 집합을 제공하고 싶습니다 . 저의 목표는 계산 가능한 워크 플로를 재현 가능한 연구 로 만드는 것 입니다.

질문

이 select 문을 쿼리 된 데이터를 새 데이터베이스로 덤프하는 스크립트에 통합하여 데이터베이스가 새 mysql 서버에 설치 될 수 있고 명령문이 새 데이터베이스와 작동 할 수있는 방법이 있습니까? 새 데이터베이스에는 쿼리에 사용 된 레코드 외에 레코드가 포함되지 않아야합니다.

업데이트 :
명확히하기 위해 쿼리 결과의 CSV 덤프에 관심이 없습니다. 내가 할 수있는 일은 데이터베이스 하위 집합을 덤프하여 다른 컴퓨터에 설치 한 다음 쿼리 자체를 재현 가능하고 동일한 데이터 세트와 관련하여 수정할 수 있도록하는 것입니다.

예를 들어, 분석에서 여러 (이 예에서는 3) 테이블의 레코드가 필요한 데이터의 하위 집합을 쿼리 할 수 ​​있습니다.

select table1.id, table1.level, table2.name, table2.level 
       from table1 join table2 on table1.id = table2.table1_id 
       join table3 on table3.id = table2.table3_id
       where table3.name in ('fee', 'fi', 'fo', 'fum'); 



답변

mysqldump 에는 주어진 테이블에 대해 WHERE 절을 실행하는 –where 옵션이 있습니다.

조인 쿼리를 mysqldump 할 수는 없지만 각 테이블에서 가져온 모든 행이 나중에 조인에 참여하도록 각 테이블에서 특정 행을 내보낼 수 있습니다.

주어진 쿼리에 대해 세 번 mysqldump해야합니다.

먼저 mysql은 이름이 ( ‘fee’, ‘fi’, ‘fo’, ‘fum’) 인 모든 table3 행을 덤프합니다.

mysqldump -u... -p... --where="name in ('fee','fi','fo','fum')" mydb table3 > table3.sql

다음으로 mysqldump는 첫 번째 mysqldump의 table3_id 값과 일치하는 모든 table2 행을 덤프합니다.

mysqldump -u... -p... --lock-all-tables --where="table3_id in (select id from table3 where name in ('fee','fi','fo','fum'))" mydb table2 > table2.sql

그런 다음 mysqldump는 두 번째 mysqldump의 table1_id 값과 일치하는 모든 table1 행을 덤프합니다.

mysqldump -u... -p... --lock-all-tables --where="id in (select table1_id from table2 where table3_id in (select id from table3 where name in ('fee','fi','fo','fum')))" mydb table1 > table1.sql

참고 : 두 번째 및 세 번째 mysqldump에는 둘 이상의 테이블을 사용해야하므로 –lock-all-tables를 사용해야합니다 .

새 데이터베이스를 작성하십시오.

mysqladmin -u... -p... mysqladmin create newdb

마지막으로, 세 개의 mysqldump를 다른 데이터베이스에로드하고 새 데이터베이스에서 조인을 시도하십시오.

mysql -u... -p... -D newdb < table1.sql
mysql -u... -p... -D newdb < table2.sql
mysql -u... -p... -D newdb < table3.sql

MySQL 클라이언트에서 조인 쿼리를 실행하십시오.

mysql> use newdb
mysql> select table1.id, table1.level, table2.name, table2.level
       from table1 join table2 on table1.id = table2.table1_id
       join table3 on table3.id = table2.table3_id
       where table3.name in ('fee', 'fi', 'fo', 'fum'); 

시도 해봐 !!!

경고 : 올바르게 색인되지 않으면 두 번째 및 세 번째 mysqldumps가 영원히 걸릴 수 있습니다!

만일을 대비하여 다음 열을 색인화하십시오.

ALTER TABLE table2 ADD INDEX (table1_id);
ALTER TABLE table2 ADD INDEX (table3_id);
ALTER TABLE table3 ADD INDEX (name,id);

id가 table3의 기본 키라고 가정하겠습니다.


답변

나는 고려할 에 ‘OUTFILE’를 사용하여 이 문제를 해결하기 위해 SELECT의 일부가 아닌 mysqldump를한다. 원하는 SELECT 문을 생성 한 다음 끝에 CSV 스타일 출력에 대한 적절한 구성으로 “INTO OUTFILE ‘/path/to/outfile.csv’…”를 추가 할 수 있습니다. 그런 다음 ‘ LOAD DATA INFILE …’구문 과 같은 것을 사용 하여 데이터를 새 스키마 위치에로드 할 수 있습니다.

예를 들어, SQL을 사용하여 :

select table1.id, table1.level, table2.name, table2.level
       from table1 join table2 on table1.id = table2.table1_id
       join table3 on table3.id = table2.table3_id
       where table3.name in ('fee', 'fi', 'fo', 'fum')
INTO OUTFILE '/tmp/fee-fi-fo-fum.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
; 

대상 디스크 파티션에 사용 가능한 저장 공간이 충분해야합니다.


답변

mysqldump 유틸리티에는 –tables 옵션 이있어 덤프 할 테이블을 지정할 수 있습니다. 테이블 목록을 지정할 수 있습니다.

나는 더 쉬운 (자동화 된) 방법을 모른다.


답변

나에게 유용한 것은 다음과 같습니다.

mysqldump -u db_user -p db_name table_name --no_create_info \
--lock-all-tables --where 'id in (SELECT tn.id FROM table_name AS tn \
JOIN related_table AS rt ON tn.related_table_id = rt.id \
WHERE rt.some_field = 1)' > data.sql

에서 http://krosinski.blogspot.com/2012/12/using-table-join-with-mysqldump.html


답변

mysql 에서 quote 함수 를 사용해 보셨습니까 ?

SELECT CONCAT("insert into table4(id,level,name,levelt2) VALUES(",   quote(table1.id),   ",",    quote(table1.level),   ",",    quote(table2.name),   ",",    quote(table2.level),    ");") as q
       from table1 join table2 on table1.id = table2.table1_id
       join table3 on table3.id = table2.table3_id
       where table3.name in ('fee', 'fi', 'fo', 'fum'); 

위의 내용을 query.sql로 저장하십시오.

cat query.sql|mysql --skip-column-names --raw > table4.sql


답변

MySQL에서 :

SHOW CREATE TABLE table1; -- use these two create statements
SHOW CREATE TABLE table2; -- to design table4's create statement
CREATE TABLE table4( .... );
INSERT INTO table4(id,level,name,levelt2)
SELECT table1.id, table1.level, table2.name, table2.level
   from table1 join table2 on table1.id = table2.table1_id
   join table3 on table3.id = table2.table3_id
   where table3.name in ('fee', 'fi', 'fo', 'fum'); 

명령 행에서 :

mysqldump mydb table4 |gzip > table4.sql.gz

대상 서버에서 ~ / .my.cnf를 설정하십시오.

[client]
default-character-set=utf8

대상 서버에서 가져 오기

zcat table4.sql.gz | mysql


답변

비슷한 문제에 대한 작은 스크립트를 작성했습니다.
https://github.com/digitalist/mysql_slice

include ('queryDumper.php');


$exampleQuery="select * from information_schema.columns c1
left join information_schema.columns c2 on 1=1 limit 1";

//define credentials
$exampleMysqli = new mysqli($host, $user, $password, $database);
$exampleResult=$exampleMysqli->query($exampleQuery);

//if  mysqlnd (native driver installed), otherwise use wrapper
$exampleData=fetchAll($exampleResult);
$exampleMeta=$exampleResult->fetch_fields();

/*
 * field content removal options
 * column name => function name in queryDumper.php, namespace QueryDumperHelpers
 *
 * */

$forbiddenFields=array(
'password'=>'replacePassword', //change password -> md5("password")
'login'=>'replaceLogin', //change login vasya@mail.ru -> vasya@example.com
'comment'=>'sanitizeComment' //lorem ipsum or
);


//get tables dump
$dump=(\queryDumper\dump($exampleData, $exampleMeta, $forbiddenFields));



$dropDatabase=true; //default false
$dropTable=true; //default false

$dbAndTablesCreationDump=\QueryDumperDatabaseAndTables\dump($exampleMysqli,$exampleMeta, $dropDatabase, $dropTable);

$databases=$dbAndTablesCreationDump['databases'];
$tables=$dbAndTablesCreationDump['tables'];
$eol=";\n\n";
echo implode($eol, $databases)."\n";
echo implode($eol, $tables).";\n";
echo "\n";

//consider using array_unique($dump) before imploding
echo implode("\n\n", $dump);
echo "\n";
?>

즉,이 쿼리가 있습니다 :

SELECT * FROM employees.employees e1
LEFT JOIN employees.employees e2 ON 1=1
LIMIT 1; 

이 덤프를 얻었습니다 .

DROP DATABASE `employees`;

CREATE DATABASE `employees`;
CREATE TABLE `employees` ( /* creation code */ ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT IGNORE INTO `employees`.`employees` VALUES ("10001","1953-09-02","Georgi","Facello","M","1986-06-26");

INSERT IGNORE INTO `employees`.`employees` VALUES ("10001","1953-09-02","Georgi","Facello","M","1986-06-26");