将具有空值的多行合并为一个
Combine several rows with null values into one
我的 select 声明有点问题。我需要 select 来自我 table 的每种类型电话的最新记录,所以我尝试此代码:
CREATE TABLE contacts(
tel_number VARCHAR2(14),
tel_type NUMBER,
row_id_con NUMBER,
record_id NUMBER
);
CREATE TABLE orders(
order_id VARCHAR2(9),
row_id_ord NUMBER
);
INSERT INTO contacts VALUES('444-444-444', 1, 1, 1);
INSERT INTO contacts VALUES('22-22-22', 2, 1, 2);
INSERT INTO contacts VALUES('555-555-555', 1, 1, 3);
INSERT INTO orders VALUES('111111111', 1);
SELECT ord.order_id,
DECODE(con.tel_type, 1, con.tel_number) AS number1,
DECODE(con.tel_type, 2, con.tel_number) AS number2
FROM (SELECT MAX(c.record_id) as max_row_id
FROM contacts c, orders o
WHERE c.row_id_con = o.row_id_ord
and o.order_id = '111111111'
GROUP BY c.tel_type) c, contacts con, orders ord
WHERE con.row_id_con = ord.row_id_ord
and con.record_id = c.max_row_id
GROUP BY ord.order_id, con.tel_type, con.tel_number;
现在的输出是这样的:
order_id number1 number2
111111111 null 22-22-22
111111111 555-555-555 null
但我需要这样的东西:
order_id number1 number2
111111111 555-555-555 22-22-22
我该怎么做?
将其用 rownum < 2 包装起来并添加 order by 以获得最大 record_id:
select * from (
SELECT ord.order_id,
DECODE(con.tel_type, 1, con.tel_number) AS number1,
DECODE(con.tel_type, 2, con.tel_number) AS number2
FROM (SELECT MAX(c.record_id) as max_row_id
FROM contacts c, orders o
WHERE c.row_id_con = o.row_id_ord
and o.order_id = '111111111'
GROUP BY c.tel_type) c, contacts con, orders ord
WHERE con.row_id_con = ord.row_id_ord
and con.record_id = c.max_row_id
GROUP BY ord.order_id, con.tel_type, con.tel_number
order by c.record_id desc
)
where rownum < 2;
您可以更改 order by 子句以获得除 c.record_id desc
之外的其他顺序
您想使用 row_number()
。像这样:
SELECT o.order_id,
MAX(CASE WHEN tel_type = 1 AND seqnum = 1 THEN tel_number END) as number1,
MAX(CASE WHEN tel_type = 2 AND seqnum = 1 THEN tel_number END) as number2
FROM (SELECT o.order_id, c.*,
ROW_NUMBER() OVER (PARTITION BY o.order_id, c.tel_type
ORDER BY record_id DESC
) as seqnum
FROM contacts c JOIN
orders o
ON c.row_id_con = o.row_id_ord AND
o.order_id = '111111111'
) o
GROUP BY order_id;
备注:
- 从不 在
FROM
子句中使用逗号。 始终使用正确、明确的JOIN
语法。
CASE
优于DECODE()
,因为它是ANSI标准SQL,所以它是标准语言的一部分。
- 您可以使用 window 函数来大大简化查询并提高性能。
- 您可以删除子查询中
order_id
的条件以获取所有订单的行。
- 您希望
GROUP BY
仅包含定义所需结果集中每一行的列。
关于更多解决方案:
SELECT o.order_id,
max( case c.tel_type when 1 then tel_number end )
KEEP ( DENSE_RANK LAST ORDER BY row_id_con NULLS FIRST ) as number1,
max( case c.tel_type when 2 then tel_number end )
KEEP ( DENSE_RANK LAST ORDER BY row_id_con NULLS FIRST ) as number2
FROM orders o
LEFT JOIN contacts c ON c.row_id_con = o.row_id_ord
GROUP BY o.order_id
;
我的 select 声明有点问题。我需要 select 来自我 table 的每种类型电话的最新记录,所以我尝试此代码:
CREATE TABLE contacts(
tel_number VARCHAR2(14),
tel_type NUMBER,
row_id_con NUMBER,
record_id NUMBER
);
CREATE TABLE orders(
order_id VARCHAR2(9),
row_id_ord NUMBER
);
INSERT INTO contacts VALUES('444-444-444', 1, 1, 1);
INSERT INTO contacts VALUES('22-22-22', 2, 1, 2);
INSERT INTO contacts VALUES('555-555-555', 1, 1, 3);
INSERT INTO orders VALUES('111111111', 1);
SELECT ord.order_id,
DECODE(con.tel_type, 1, con.tel_number) AS number1,
DECODE(con.tel_type, 2, con.tel_number) AS number2
FROM (SELECT MAX(c.record_id) as max_row_id
FROM contacts c, orders o
WHERE c.row_id_con = o.row_id_ord
and o.order_id = '111111111'
GROUP BY c.tel_type) c, contacts con, orders ord
WHERE con.row_id_con = ord.row_id_ord
and con.record_id = c.max_row_id
GROUP BY ord.order_id, con.tel_type, con.tel_number;
现在的输出是这样的:
order_id number1 number2
111111111 null 22-22-22
111111111 555-555-555 null
但我需要这样的东西:
order_id number1 number2
111111111 555-555-555 22-22-22
我该怎么做?
将其用 rownum < 2 包装起来并添加 order by 以获得最大 record_id:
select * from (
SELECT ord.order_id,
DECODE(con.tel_type, 1, con.tel_number) AS number1,
DECODE(con.tel_type, 2, con.tel_number) AS number2
FROM (SELECT MAX(c.record_id) as max_row_id
FROM contacts c, orders o
WHERE c.row_id_con = o.row_id_ord
and o.order_id = '111111111'
GROUP BY c.tel_type) c, contacts con, orders ord
WHERE con.row_id_con = ord.row_id_ord
and con.record_id = c.max_row_id
GROUP BY ord.order_id, con.tel_type, con.tel_number
order by c.record_id desc
)
where rownum < 2;
您可以更改 order by 子句以获得除 c.record_id desc
您想使用 row_number()
。像这样:
SELECT o.order_id,
MAX(CASE WHEN tel_type = 1 AND seqnum = 1 THEN tel_number END) as number1,
MAX(CASE WHEN tel_type = 2 AND seqnum = 1 THEN tel_number END) as number2
FROM (SELECT o.order_id, c.*,
ROW_NUMBER() OVER (PARTITION BY o.order_id, c.tel_type
ORDER BY record_id DESC
) as seqnum
FROM contacts c JOIN
orders o
ON c.row_id_con = o.row_id_ord AND
o.order_id = '111111111'
) o
GROUP BY order_id;
备注:
- 从不 在
FROM
子句中使用逗号。 始终使用正确、明确的JOIN
语法。 CASE
优于DECODE()
,因为它是ANSI标准SQL,所以它是标准语言的一部分。- 您可以使用 window 函数来大大简化查询并提高性能。
- 您可以删除子查询中
order_id
的条件以获取所有订单的行。 - 您希望
GROUP BY
仅包含定义所需结果集中每一行的列。
关于更多解决方案:
SELECT o.order_id,
max( case c.tel_type when 1 then tel_number end )
KEEP ( DENSE_RANK LAST ORDER BY row_id_con NULLS FIRST ) as number1,
max( case c.tel_type when 2 then tel_number end )
KEEP ( DENSE_RANK LAST ORDER BY row_id_con NULLS FIRST ) as number2
FROM orders o
LEFT JOIN contacts c ON c.row_id_con = o.row_id_ord
GROUP BY o.order_id
;