我正在尝试将一个表放在记录中,这些记录是三个字符串的簇,并返回一个查询,其中数据在一个记录中。
表定义是:
CREATE TABLE Xerox.FIM2 (
KPIN CHAR(18) NOT NULL COMMENT 'Part Number',
KSEQ DECIMAL(2, 0) NOT NULL COMMENT 'Sequence Number',
SDS1 CHAR(40) NOT NULL COMMENT 'Supplemental Description 1',
SDS2 CHAR(30) NOT NULL COMMENT 'Supplemental Description 2',
SDS3 CHAR(30) NOT NULL COMMENT 'Supplemental Description 3',
PRIMARY KEY (KPIN, KSEQ),
INDEX IDX_FIM2_KSEQ (KSEQ),
INDEX IDX_FIM2_SDS1 (SDS1),
INDEX IDX_FIM2_SDS2 (SDS2),
INDEX IDX_FIM2_SDS3 (SDS3),
INDEX UK_FIM2_KPIN (KPIN)
)
ENGINE = INNODB
AVG_ROW_LENGTH = 180
CHARACTER SET latin1
COLLATE latin1_swedish_ci
COMMENT = 'Supplemental Part Descriptions';
给定的部件号可能没有记录或最多8条记录。这八个记录包含我试图转换的字符串数据(描述,每个记录三个):
KPIN KSEQ SDS1 SDS2 SDS3
R0205 1 COLD ROLLED A1008/A CS TYPE B MATTE FINISH OIL / EXPOSED MIN YIELD 30,000 RB 45-60
R0205 2 THICKNESS .032 TOL +.006/-.000 WIDTH 48.000 TOL +.188/-.000 LENGTH 84.875 TOL +/-.020
R0205 3 SQUARENESS TOL +/-.062 MAX LIFT WEIGHT 10,000 LBS <null>
以下数据:
KPIN KSEQ DES1 DES2 DES3 DES4 DES5 DES6 DES7 DES8 DES9 DES10 DES11 DES12
R0205 1 COLD ROLLED A1008/A CS TYPE B MATTE FINISH OIL / EXPOSED MIN YIELD 30,000 RB 45-60 THICKNESS .032 TOL +.006/-.000 WIDTH 48.000 TOL +.188/-.000 LENGTH 84.875 TOL +/-.020 THICKNESS .032 TOL +.006/-.000 WIDTH 48.000 TOL +.188/-.000 LENGTH 84.875 TOL +/-.020 SQUARENESS TOL +/-.062 MAX LIFT WEIGHT 10,000 LBS <null><null><null><null>...
执行此操作的SQL命令是:
SELECT FIM1.KPIN, FIM1.DES, p.DES1, p.DES2, p.DES3, p.DES4, p.DES5, p.DES6,
p.DES7, p.DES8, p.DES9, p.DES10, p.DES11, p.DES12,
p.DES13, p.DES14, p.DES15, p.DES16, p.DES17, p.DES18,
p.DES19, p.DES20, p.DES21, p.DES22, p.DES23, p.DES24
FROM FIM1
JOIN
(SELECT KPIN, KSEQ,
MAX(CASE WHEN (KSEQ = 1) THEN SDS1 END) AS DES1,
MAX(CASE WHEN (KSEQ = 1) THEN SDS2 END) AS DES2,
MAX(CASE WHEN (KSEQ = 1) THEN SDS3 END) AS DES3,
MAX(CASE WHEN (KSEQ = 2) THEN SDS1 END) AS DES4,
MAX(CASE WHEN (KSEQ = 2) THEN SDS2 END) AS DES5,
MAX(CASE WHEN (KSEQ = 2) THEN SDS3 END) AS DES6,
MAX(CASE WHEN (KSEQ = 3) THEN SDS1 END) AS DES7,
MAX(CASE WHEN (KSEQ = 3) THEN SDS2 END) AS DES8,
MAX(CASE WHEN (KSEQ = 3) THEN SDS3 END) AS DES9,
MAX(CASE WHEN (KSEQ = 4) THEN SDS1 END) AS DES10,
MAX(CASE WHEN (KSEQ = 4) THEN SDS2 END) AS DES11,
MAX(CASE WHEN (KSEQ = 4) THEN SDS3 END) AS DES12,
MAX(CASE WHEN (KSEQ = 5) THEN SDS1 END) AS DES13,
MAX(CASE WHEN (KSEQ = 5) THEN SDS2 END) AS DES14,
MAX(CASE WHEN (KSEQ = 5) THEN SDS3 END) AS DES15,
MAX(CASE WHEN (KSEQ = 6) THEN SDS1 END) AS DES16,
MAX(CASE WHEN (KSEQ = 6) THEN SDS2 END) AS DES17,
MAX(CASE WHEN (KSEQ = 6) THEN SDS3 END) AS DES18,
MAX(CASE WHEN (KSEQ = 7) THEN SDS1 END) AS DES19,
MAX(CASE WHEN (KSEQ = 7) THEN SDS2 END) AS DES20,
MAX(CASE WHEN (KSEQ = 7) THEN SDS3 END) AS DES21,
MAX(CASE WHEN (KSEQ = 8) THEN SDS1 END) AS DES22,
MAX(CASE WHEN (KSEQ = 8) THEN SDS2 END) AS DES23,
MAX(CASE WHEN (KSEQ = 8) THEN SDS3 END) AS DES24
FROM FIM2
GROUP BY KPIN
ORDER BY KPIN, KSEQ) as p
ON FIM1.KPIN=p.KPIN ORDER BY FIM1.KPIN
表FIM1(主要部件编号列表)中有118,552条记录
表FIM2中有66,303条记录(所有这些描述)
表FIM1中的62,163条记录在FIM2中至少有一条描述记录。
上面写的查询在大约3秒内返回62,163条记录。如果我将其更改为LEFT JOIN而不是JOIN,我希望得到所有118,552条记录,其中包含大量空值。该操作需要几分钟和几分钟才能完成。我想理解为什么这两个操作之间存在如此巨大的差异。似乎LEFT JOIN强制引擎一次又一次地遍历FIM2表,但是为什么它不必为简单的JOIN做那个呢?我意识到我正在为每个项目创建类似临时记录的东西,但简单的连接仍然能够优化它。
此行合并技术基于此处详述的概念: How to pivot? How to convert multiple rows into one row with multiple columns?
我的查询计划: (对于JOIN):
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL (null) (null) (null) (null) 64512 Using temporary; Using filesort
1 PRIMARY FIM1 eq_ref PRIMARY,UK_FIM1_KPIN PRIMARY 18 p.KPIN 1
2 DERIVED FIM2 index (null) PRIMARY 19 (null) 64085 Using temporary; Using filesort
LEFT JOIN的:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY FIM1 index (null) IDX_FIM1_DES 30 (null) 124199 Using index; Using temporary; Using filesort
1 PRIMARY <derived2> ALL (null) (null) (null) (null) 64512
2 DERIVED FIM2 index (null) PRIMARY 19 (null) 64085 Using temporary; Using filesort
答案 0 :(得分:3)
FIM2
表,那么每行只有一个而不是三个吗?如果你这样做,你的生活将会变得更容易。
KPIN KSEQ KFLD ATTRIBUTE
R0205 1 1 COLD ROLLED A1008/A CS TYPE B
R0205 1 2 MATTE FINISH OIL / EXPOSED
R0205 1 3 MIN YIELD 30,000 RB 45-60
R0205 2 1 THICKNESS .032 TOL +.006/-.000
R0205 2 2 WIDTH 48.000 TOL +.188/-.000
R0205 2 3 LENGTH 84.875 TOL +/-.020
R0205 3 1 SQUARENESS TOL +/-.062
R0205 3 2 MAX LIFT WEIGHT 10,000 LBS
但是,那不是你问的。您希望改进报告程序,以便在合理的时间内LEFT JOIN
这两个表。
分解您的查询非常重要。首先,您尝试LEFT JOIN
FIM1
和FIM2
表,然后转动结果集以将内容扩展为一行。
你的方法在功能上是正确的,首先是旋转,然后是加入。让我们尝试另一种方法,首先加入,然后转动。这应该减少满足查询所需的数字运算次数。
SELECT ff.KPIN, ff.DES,
a.SDS1 AS DES1,
a.SDS2 AS DES2,
a.SDS3 AS DES3,
b.SDS1 AS DES4,
b.SDS2 AS DES5,
b.SDS3 AS DES6,
c.SDS1 AS DES7,
c.SDS2 AS DES8, ...
h.SDS1 AS DES23,
h.SDS2 AS DES24
FROM FIM1 AS ff
LEFT JOIN FIM2 AS a ON ff.KPIN = a.KPIN AND a.KSEQ=1
LEFT JOIN FIM2 AS b ON ff.KPIN = b.KPIN AND b.KSEQ=2
LEFT JOIN FIM2 AS c ON ff.KPIN = c.KPIN AND c.KSEQ=3
LEFT JOIN FIM2 AS d ON ff.KPIN = d.KPIN AND d.KSEQ=4
LEFT JOIN FIM2 AS e ON ff.KPIN = e.KPIN AND e.KSEQ=5
LEFT JOIN FIM2 AS f ON ff.KPIN = f.KPIN AND f.KSEQ=6
LEFT JOIN FIM2 AS g ON ff.KPIN = g.KPIN AND g.KSEQ=7
LEFT JOIN FIM2 AS h ON ff.KPIN = h.KPIN AND h.KSEQ=8
如果使用复合索引FIM2
索引(KSEQ, KPIN)
,这可能会非常快。通过八次LEFT JOIN
操作确实看起来很毛茸茸,但你的MAX() ... GROUP BY
查询也很毛茸茸。您还应该尝试使用索引(KSEQ,KPIN)
来查看哪个更快。