如何使用可变但数量有限的匹配条目转置 table
How to transpose a table with a variable but limited number of matching entries
我正在使用以下 table DDL:
CREATE TABLE foo (
globalkey INTEGER NOT NULL,
subkey INTEGER NOT NULL,
type VARCHAR(3) NOT NULL,
bar VARCHAR(4) NOT NULL
);
table 包含不同类型的记录(例如 "t1"、"t2" 和 "t3")。 table 的主键是 (globalkey, subkey)。对于每个全局键,可以有 1-n 条记录,其中一些可能共享相同的类型。但是只有 0-3 条类型为 "t1".
的记录
我想创建一个查询,为我提供至少有一个类型为 "t1" 和 returns 的所有全局键,结果中的 3 个栏值作为 3 个不同的列。
所以对于给定的数据:
GLOBALKEY, SUBKEY, TYPE, BAR
1 1 t1 hit1
1 28 t1 hit1234
1 315 t2 miss
1 967 t1 hit4711
2 1 t5 miss
2 13 t5 miss
2 18 t1 hit9876
3 1 t2 miss
我想得到:
GLOBALKEY, BAR1, BAR2, BAR3
1, "hit1", "hit1234", "hit4711"
3, "hit9876", NULL , NULL
我在下面创建了一个 SQLFiddle:http://sqlfiddle.com/#!9/04855
对于如何完成此操作的任何指示,我将不胜感激!
再见,
马库斯
更新 #1:在我的初始版本中,我没有足够清楚地说明 BAR 列包含任意值,因此我无法使用 @Mita 语句的确切版本,因为这假定了case 语句是固定的('hit1'、'hit2'、...)。但是与此同时,我发现了如何使用 row_number() window 函数来克服这个问题。查看我对@Mita 答案的编辑。相应地更新了 SQLFiddle...
JSFiddle 插入内容与您在示例中提供的数据不一致。正确的数据应该是:
INSERT INTO foo VALUES (1,1,'t1','hit1');
INSERT INTO foo VALUES (1,28,'t1','hit2');
INSERT INTO foo VALUES (1,315,'t2','miss');
INSERT INTO foo VALUES (1,967,'t1','hit3');
INSERT INTO foo VALUES (2,1,'t5','miss');
INSERT INTO foo VALUES (2,13,'t5','miss');
INSERT INTO foo VALUES (2,18,'t1','hit1');
INSERT INTO foo VALUES (3,1,'t2','miss');
查询(如果我没理解错的话)应该是:
SELECT
globalkey,
MAX(CASE WHEN bar = 'hit1' THEN 'hit1' ELSE NULL END) AS bar1,
MAX(CASE WHEN bar = 'hit2' THEN 'hit2' ELSE NULL END) AS bar2,
MAX(CASE WHEN bar = 'hit3' THEN 'hit3' ELSE NULL END) AS bar3
FROM
foo
WHERE
type = 't1'
GROUP BY
globalkey
更新 #1:Mita 的查询假定 'hit1'、'hit2'、... 是固定值。在我的示例中,它们没有被枚举,但可以是任何文本。但是,通过使用 window 函数,您可以实现我想要的。首先 select 所有匹配行 (type='t1') 并在当前全局键中添加一个包含行号的新列。
使用这个中间结果集,然后可以转置类似于@MITA 答案的table。
所以在 DB2 中你可以这样做:
WITH tmp1 AS (SELECT globalkey, bar, row_number() OVER (partition by globalkey) AS rnr
WHERE
type='t1'
)
SELECT globalkey,
MAX(CASE WHEN rnr = 1 THEN bar ELSE NULL END) AS bar1,
MAX(CASE WHEN rnr = 2 THEN bar ELSE NULL END) AS bar2,
MAX(CASE WHEN rnr = 3 THEN bar ELSE NULL END) AS bar3
FROM
foo
WHERE
type = 't1'
GROUP BY
globalkey
我正在使用以下 table DDL:
CREATE TABLE foo (
globalkey INTEGER NOT NULL,
subkey INTEGER NOT NULL,
type VARCHAR(3) NOT NULL,
bar VARCHAR(4) NOT NULL
);
table 包含不同类型的记录(例如 "t1"、"t2" 和 "t3")。 table 的主键是 (globalkey, subkey)。对于每个全局键,可以有 1-n 条记录,其中一些可能共享相同的类型。但是只有 0-3 条类型为 "t1".
的记录我想创建一个查询,为我提供至少有一个类型为 "t1" 和 returns 的所有全局键,结果中的 3 个栏值作为 3 个不同的列。
所以对于给定的数据:
GLOBALKEY, SUBKEY, TYPE, BAR
1 1 t1 hit1
1 28 t1 hit1234
1 315 t2 miss
1 967 t1 hit4711
2 1 t5 miss
2 13 t5 miss
2 18 t1 hit9876
3 1 t2 miss
我想得到:
GLOBALKEY, BAR1, BAR2, BAR3
1, "hit1", "hit1234", "hit4711"
3, "hit9876", NULL , NULL
我在下面创建了一个 SQLFiddle:http://sqlfiddle.com/#!9/04855
对于如何完成此操作的任何指示,我将不胜感激!
再见,
马库斯
更新 #1:在我的初始版本中,我没有足够清楚地说明 BAR 列包含任意值,因此我无法使用 @Mita 语句的确切版本,因为这假定了case 语句是固定的('hit1'、'hit2'、...)。但是与此同时,我发现了如何使用 row_number() window 函数来克服这个问题。查看我对@Mita 答案的编辑。相应地更新了 SQLFiddle...
JSFiddle 插入内容与您在示例中提供的数据不一致。正确的数据应该是:
INSERT INTO foo VALUES (1,1,'t1','hit1');
INSERT INTO foo VALUES (1,28,'t1','hit2');
INSERT INTO foo VALUES (1,315,'t2','miss');
INSERT INTO foo VALUES (1,967,'t1','hit3');
INSERT INTO foo VALUES (2,1,'t5','miss');
INSERT INTO foo VALUES (2,13,'t5','miss');
INSERT INTO foo VALUES (2,18,'t1','hit1');
INSERT INTO foo VALUES (3,1,'t2','miss');
查询(如果我没理解错的话)应该是:
SELECT
globalkey,
MAX(CASE WHEN bar = 'hit1' THEN 'hit1' ELSE NULL END) AS bar1,
MAX(CASE WHEN bar = 'hit2' THEN 'hit2' ELSE NULL END) AS bar2,
MAX(CASE WHEN bar = 'hit3' THEN 'hit3' ELSE NULL END) AS bar3
FROM
foo
WHERE
type = 't1'
GROUP BY
globalkey
更新 #1:Mita 的查询假定 'hit1'、'hit2'、... 是固定值。在我的示例中,它们没有被枚举,但可以是任何文本。但是,通过使用 window 函数,您可以实现我想要的。首先 select 所有匹配行 (type='t1') 并在当前全局键中添加一个包含行号的新列。
使用这个中间结果集,然后可以转置类似于@MITA 答案的table。
所以在 DB2 中你可以这样做:
WITH tmp1 AS (SELECT globalkey, bar, row_number() OVER (partition by globalkey) AS rnr
WHERE
type='t1'
)
SELECT globalkey,
MAX(CASE WHEN rnr = 1 THEN bar ELSE NULL END) AS bar1,
MAX(CASE WHEN rnr = 2 THEN bar ELSE NULL END) AS bar2,
MAX(CASE WHEN rnr = 3 THEN bar ELSE NULL END) AS bar3
FROM
foo
WHERE
type = 't1'
GROUP BY
globalkey