Mysql group_concat의 반복 키 및 1개의 쿼리에서 여러 열의 반복 횟수(Query Optimization)
이 질문은 PHP를 통한 데이터베이스 호출을 피하기 위한 쿼리 최적화에 관한 것입니다.
이 시나리오에는 2개의 테이블이 있습니다.하나는 참조 테이블이라고 부를 수 있는 정보가 포함되어 있고 다른 하나는 데이터 테이블, 필드입니다.key1
그리고.key2
두 표에서 공통으로 볼 수 있습니다.이러한 필드에 근거하여 이들 필드를 결합할 수 있습니다.
제가 지금 하고 있는 것보다 더 간단하게 질의를 할 수 있을지 모르겠습니다.제가 달성하고 싶은 것은 다음과 같습니다.
나는 다른 것을 찾고 싶다
key1,key2,info1,info2
부터main_info
테이블, 시리얼 값이 10 미만이고key1,key2
두 테이블이 일치하는지 확인한 다음, 다음으로 그룹화합니다.info1,info2
그룹화는 반복 횟수를 카운트합니다.key1,key2
을 복제하기 위해info1,info2
필드 및group_concat
그 열쇠들
표 내용main_info
MariaDB [demos]> select * from main_info;
+------+------+-------+-------+----------+
| key1 | key2 | info1 | info2 | date |
+------+------+-------+-------+----------+
| 1 | 1 | 15 | 90 | 20120501 |
| 1 | 2 | 14 | 92 | 20120601 |
| 1 | 3 | 15 | 82 | 20120801 |
| 1 | 4 | 15 | 82 | 20120801 |
| 1 | 5 | 15 | 82 | 20120802 |
| 2 | 1 | 17 | 90 | 20130302 |
| 2 | 2 | 17 | 90 | 20130302 |
| 2 | 3 | 17 | 90 | 20130302 |
| 2 | 4 | 16 | 88 | 20130601 |
+------+------+-------+-------+----------+
9 rows in set (0.00 sec)
표 내용product1
MariaDB [demos]> select * from product1;
+------+------+--------+--------------+
| key1 | key2 | serial | product_data |
+------+------+--------+--------------+
| 1 | 1 | 0 | NaN |
| 1 | 1 | 1 | NaN |
| 1 | 1 | 2 | NaN |
| 1 | 1 | 3 | NaN |
| 1 | 2 | 0 | 12.556 |
| 1 | 2 | 1 | 13.335 |
| 1 | 3 | 1 | NaN |
| 1 | 3 | 2 | 13.556 |
| 1 | 3 | 3 | 14.556 |
| 1 | 4 | 3 | NaN |
| 1 | 5 | 3 | NaN |
| 2 | 1 | 0 | 12.556 |
| 2 | 1 | 1 | 13.553 |
| 2 | 1 | 2 | NaN |
| 2 | 2 | 12 | 129 |
| 2 | 3 | 22 | NaN |
+------+------+--------+--------------+
16 rows in set (0.00 sec)
PHP I 그룹 필드 경유info1
그리고.info2
테이블의main_info
, 현재 컨텍스트에서serial
,product_data
테이블의product1
, 여러 번 연속해서 (여기서는 보시는 바와 같이 두 번 쿼리를 실행하고 있습니다)
필드용serial
- 첫 번째 쿼리
MariaDB [demos]> select * , count(*) as serial_count,GROUP_CONCAT(key1,' ',key2) as serial_ids from
-> (
-> SELECT distinct
-> if(b.serial < 10,a.key1,null) AS `key1`,
-> if(b.serial < 10,a.key2,null) AS `key2`,
-> if(b.serial < 10,a.info1,null) AS `info1`,
-> if(b.serial < 10,a.info2,null) AS `info2`
-> FROM main_info a inner join product1 b on a.key1 = b.key1 AND a.key2= b.key2
-> ) as sub group by info1,info2
-> ;
+------+------+-------+-------+--------------+-------------+
| key1 | key2 | info1 | info2 | serial_count | serial_ids |
+------+------+-------+-------+--------------+-------------+
| NULL | NULL | NULL | NULL | 1 | NULL |
| 1 | 2 | 14 | 92 | 1 | 1 2 |
| 1 | 3 | 15 | 82 | 3 | 1 3,1 4,1 5 |
| 1 | 1 | 15 | 90 | 1 | 1 1 |
| 2 | 1 | 17 | 90 | 1 | 2 1 |
+------+------+-------+-------+--------------+-------------+
5 rows in set (0.00 sec)
필드용product_data
- 두 번째 질문
MariaDB [demos]> select * , count(*) as product_data_count,GROUP_CONCAT(key1,' ',key2) as product_data_ids from
-> (
-> SELECT distinct
-> if(b.product_data IS NOT NULL,a.key1,null) AS `key1`,
-> if(b.product_data IS NOT NULL,a.key2,null) AS `key2`,
-> if(b.product_data IS NOT NULL,a.info1,null) AS `info1`,
-> if(b.product_data IS NOT NULL,a.info2,null) AS `info2`
-> FROM main_info a inner join product1 b on a.key1 = b.key1 AND a.key2= b.key2
-> ) as sub group by info1,info2
-> ;
+------+------+-------+-------+--------------------+------------------+
| key1 | key2 | info1 | info2 | product_data_count | product_data_ids |
+------+------+-------+-------+--------------------+------------------+
| 1 | 2 | 14 | 92 | 1 | 1 2 |
| 1 | 3 | 15 | 82 | 3 | 1 3,1 4,1 5 |
| 1 | 1 | 15 | 90 | 1 | 1 1 |
| 2 | 2 | 17 | 90 | 3 | 2 2,2 3,2 1 |
+------+------+-------+-------+--------------------+------------------+
4 rows in set (0.01 sec)
Group by info1, info2라는 하나의 쿼리를 사용하여 이와 같이 출력하고 싶습니다.
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| key1 | key2 | info1 | info2 | serial_count | serial_ids | product_data_count | product_data_ids |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| NULL | NULL | NULL | NULL | 1 | NULL | NULL | NULL |
| 1 | 2 | 14 | 92 | 1 | 1 2 | 1 | 1 2 |
| 1 | 3 | 15 | 82 | 3 | 1 3,1 4,1 5 | 3 | 1 3,1 4,1 5 |
| 1 | 1 | 15 | 90 | 1 | 1 1 | 1 | 1 1 |
| 2 | 1 | 17 | 90 | 1 | 2 1 | 3 | 2 2,2 3,2 1 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
아래는 테이블의 구조입니다.
DROP TABLE IF EXISTS `main_info`;
CREATE TABLE `main_info` (
`key1` int(11) NOT NULL,
`key2` int(11) NOT NULL,
`info1` int(11) NOT NULL,
`info2` int(11) NOT NULL,
`date` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
LOCK TABLES `main_info` WRITE;
INSERT INTO `main_info` VALUES (1,1,15,90,20120501),(1,2,14,92,20120601),(1,3,15,82,20120801),(1,4,15,82,20120801),(1,5,15,82,20120802),(2,1,17,90,20130302),(2,2,17,90,20130302),(2,3,17,90,20130302),(2,4,16,88,20130601);
UNLOCK TABLES;
DROP TABLE IF EXISTS `product1`;
CREATE TABLE `product1` (
`key1` int(11) NOT NULL,
`key2` int(11) NOT NULL,
`serial` int(11) NOT NULL,
`product_data` varchar(1000) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
LOCK TABLES `product1` WRITE;
INSERT INTO `product1` VALUES (1,1,0,'NaN'),(1,1,1,'NaN'),(1,1,2,'NaN'),(1,1,3,'NaN'),(1,2,0,'12.556'),(1,2,1,'13.335'),(1,3,1,'NaN'),(1,3,2,'13.556'),(1,3,3,'14.556'),(1,4,3,'NaN'),(1,5,3,'NaN'),(2,1,0,'12.556'),(2,1,1,'13.553'),(2,1,2,'NaN'),(2,2,12,'129'),(2,3,22,'NaN');
UNLOCK TABLES;
한 번의 질문으로 결과를 얻을 수 있도록 도와주세요.
두 개의 쿼리를 JOIN과 결합하는 것은 어떻습니까?
SQL:
SELECT
tbl1.key1, tbl1.key2, tbl1.info1, tbl1.info2, tbl1.serial_count, tbl1.serial_ids,
tbl2.product_data_count, tbl2.product_data_ids
FROM
(
select * , count(*) as serial_count,GROUP_CONCAT(key1,' ',key2) as serial_ids from
(
SELECT distinct
if(b.serial < 10,a.key1,null) AS `key1`,
if(b.serial < 10,a.key2,null) AS `key2`,
if(b.serial < 10,a.info1,null) AS `info1`,
if(b.serial < 10,a.info2,null) AS `info2`
FROM main_info a inner join product1 b on a.key1 = b.key1 AND a.key2= b.key2
) as sub group by info1,info2
) tbl1
LEFT OUTER JOIN
(
select * , count(*) as product_data_count,GROUP_CONCAT(key1,' ',key2) as product_data_ids from
(
SELECT distinct
if(b.product_data IS NOT NULL,a.key1,null) AS `key1`,
if(b.product_data IS NOT NULL,a.key2,null) AS `key2`,
if(b.product_data IS NOT NULL,a.info1,null) AS `info1`,
if(b.product_data IS NOT NULL,a.info2,null) AS `info2`
FROM main_info a inner join product1 b on a.key1 = b.key1 AND a.key2= b.key2
) as sub group by info1,info2
) tbl2
ON tbl1.info1 = tbl2.info1 AND tbl1.info2 = tbl2.info2
ORDER BY 3,4
;
출력:
mysql> SELECT
-> tbl1.key1, tbl1.key2, tbl1.info1, tbl1.info2, tbl1.serial_count, tbl1.serial_ids,
-> tbl2.product_data_count, tbl2.product_data_ids
-> FROM
-> (
-> select * , count(*) as serial_count,GROUP_CONCAT(key1,' ',key2) as serial_ids from
-> (
-> SELECT distinct
-> if(b.serial < 10,a.key1,null) AS `key1`,
-> if(b.serial < 10,a.key2,null) AS `key2`,
-> if(b.serial < 10,a.info1,null) AS `info1`,
-> if(b.serial < 10,a.info2,null) AS `info2`
-> FROM main_info a inner join product1 b on a.key1 = b.key1 AND a.key2= b.key2
-> ) as sub group by info1,info2
-> ) tbl1
-> LEFT OUTER JOIN
-> (
-> select * , count(*) as product_data_count,GROUP_CONCAT(key1,' ',key2) as product_data_ids from
-> (
-> SELECT distinct
-> if(b.product_data IS NOT NULL,a.key1,null) AS `key1`,
-> if(b.product_data IS NOT NULL,a.key2,null) AS `key2`,
-> if(b.product_data IS NOT NULL,a.info1,null) AS `info1`,
-> if(b.product_data IS NOT NULL,a.info2,null) AS `info2`
-> FROM main_info a inner join product1 b on a.key1 = b.key1 AND a.key2= b.key2
-> ) as sub group by info1,info2
-> ) tbl2
-> ON tbl1.info1 = tbl2.info1 AND tbl1.info2 = tbl2.info2
-> ORDER BY 3,4
-> ;
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| key1 | key2 | info1 | info2 | serial_count | serial_ids | product_data_count | product_data_ids |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| NULL | NULL | NULL | NULL | 1 | NULL | NULL | NULL |
| 1 | 2 | 14 | 92 | 1 | 1 2 | 1 | 1 2 |
| 1 | 3 | 15 | 82 | 3 | 1 3,1 4,1 5 | 3 | 1 3,1 4,1 5 |
| 1 | 1 | 15 | 90 | 1 | 1 1 | 1 | 1 1 |
| 2 | 1 | 17 | 90 | 1 | 2 1 | 3 | 2 2,2 3,2 1 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
5 rows in set (0.01 sec)
mysql> select version();
+-----------------+
| version() |
+-----------------+
| 10.1.10-MariaDB |
+-----------------+
1 row in set (0.00 sec)
이거 드셔보세요.
SELECT
key1, key2, info1, info2,
SUM(Scount) AS serial_count, GROUP_CONCAT(Skey1, ' ', Skey2) AS serial_ids,
SUM(Pcount) AS product_data_count, GROUP_CONCAT(Pkey1, ' ', Pkey2) AS product_data_ids
FROM
(
SELECT DISTINCT
IF(b.serial < 10 OR b.product_data IS NOT NULL,a.key1, NULL) AS `key1`,
IF(b.serial < 10 OR b.product_data IS NOT NULL,a.key2, NULL) AS `key2`,
IF(b.serial < 10 OR b.product_data IS NOT NULL,a.info1, NULL) AS `info1`,
IF(b.serial < 10 OR b.product_data IS NOT NULL,a.info2, NULL) AS `info2`,
IF(b.serial < 10,a.key1, NULL) AS `Skey1`,
IF(b.serial < 10,a.key2, NULL) AS `Skey2`,
IF(b.product_data IS NOT NULL,a.key1, NULL) AS `Pkey1`,
IF(b.product_data IS NOT NULL,a.key2, NULL) AS `Pkey2`,
IF(b.serial < 10, 1, NULL) AS `Scount`,
IF(b.product_data IS NOT NULL, 1, NULL) AS `Pcount`
FROM main_info a INNER JOIN product1 b ON a.key1 = b.key1 AND a.key2= b.key2
UNION ALL
SELECT DISTINCT
NULL AS `key1`,
NULL AS `key2`,
NULL AS `info1`,
NULL AS `info2`,
NULL AS `Skey1`,
NULL AS `Skey2`,
NULL AS `Pkey1`,
NULL AS `Pkey2`,
IF(serial > 9, 1, NULL) AS `Scount`,
IF(product_data IS NULL, 1, NULL) AS `Pcount`
FROM product1 WHERE serial > 9 xor product_data IS NULL
) AS sub GROUP BY info1,info2
결과(질문의 데이터)
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| key1 | key2 | info1 | info2 | serial_count | serial_ids | product_data_count | product_data_ids |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| NULL | NULL | NULL | NULL | 1 | NULL | NULL | NULL |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| 1 | 2 | 14 | 92 | 1 | 1 2 | 1 | 1 2 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| 1 | 3 | 15 | 82 | 3 | 1 3,1 4,1 5 | 3 | 1 3,1 4,1 5 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| 1 | 1 | 15 | 90 | 1 | 1 1 | 1 | 1 1 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
RESULT(코멘트
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| key1 | key2 | info1 | info2 | serial_count | serial_ids | product_data_count | product_data_ids |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| NULL | NULL | NULL | NULL | 1 | NULL | 1 | NULL |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| 1 | 2 | 14 | 92 | 1 | 1 2 | 1 | 1 2 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| 1 | 3 | 15 | 82 | 3 | 1 3,1 4,1 5 | 3 | 1 3,1 4,1 5 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| 1 | 1 | 15 | 90 | 1 | 1 1 | 1 | 1 1 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| 2 | 4 | 16 | 88 | 1 | 2 4 | 1 | 2 4 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
| 2 | 1 | 17 | 90 | NULL | NULL | 3 | 2 1,2 2,2 3 |
+------+------+-------+-------+--------------+-------------+--------------------+------------------+
주의:
질문의 이면에 있는 기본 논리에 대해 정말 이해할 수 있는 부분이 있기 때문에, 주로 예상한 결과에 근거해 대답하십시오.예를 들어 if group 필드(info1
그리고.info2
)는 null입니다.다른 결과는 항상 null입니다.serial_count
그리고.product_data_count
1이 될 수도 있고 0이 될 수도 있는데, 정말 그걸 받으려고 한 거야?이 답변에서는 다음 서브쿼리가 사용됩니다.UNION ALL
그걸 만족시키기 위해서요.
당신의 견적을 보면 다음과 같은 일을 하고 싶은 것 같습니다(SQLfiddle).
SELECT
m.info1,
m.info2,
COUNT(DISTINCT CONCAT(m.key1, ' ', m.key2)) key_count,
GROUP_CONCAT(DISTINCT CONCAT(m.key1, ' ', m.key2) ORDER BY m.key1, m.key2) key_pairs,
COUNT(DISTINCT p.serial) serial_count,
GROUP_CONCAT(DISTINCT p.serial ORDER BY p.serial) serials,
COUNT(DISTINCT p.product_data) data_count,
GROUP_CONCAT(DISTINCT p.product_data ORDER BY p.product_data) product_data
FROM
main_info m INNER JOIN
product1 p ON p.key1 = m.key1 AND p.key2 = m.key2
WHERE
p.serial < 10
GROUP BY
m.info1,
m.info2
고유한 값을 세어 나열하는 것이 맞습니까?info1, info2로만 그룹화할 수 없으며, 결과에서 key1 또는 key2에 대한 열도 가질 수 있습니다(예: min(key1) 또는 max(key2)가 작동합니다).위의 문의를 통해 조정했습니다만, 당신의 결과와는 상당히 다르지만, 몇 가지 변경이 있을 수 있습니다.
언급URL : https://stackoverflow.com/questions/35538092/mysql-group-concat-of-repeated-keys-and-count-of-repetition-of-multiple-columns
'programing' 카테고리의 다른 글
마리아에 잠긴 채로 건너뛸 수도 있습니다.DB (0) | 2022.11.27 |
---|---|
Mysql에서 id를 사용하여 테이블에서 많은 행 삭제 (0) | 2022.11.27 |
Storybook이 Vue 프로젝트의 컴포넌트에 SVG를 로드하지 않음 (0) | 2022.11.27 |
txt 파일의 각 행을 새 어레이 요소로 읽습니다. (0) | 2022.11.27 |
조건부로 클래스 속성을 적용하는 React Js (0) | 2022.11.27 |