SQL 多对一联接 - 如何获取空白字段而不是重复值
SQL many-to-one join - how to get blank fields instead of duplicated values
我有 3 个表:
CREATE TABLE ticket (
ticket_id int,
description varchar(1000));
CREATE TABLE document (
ticket_id int,
file_name varchar(1000));
CREATE TABLE flex_fields (
ticket_id int,
field_name varchar(1000),
field_value varchar(1000));
当我通过 ticket_id 加入这个表并查询时,我得到这样的结果:
ticket_id description file_name field_name field_value
4374959 some_description1 file1.txt created_date 12-12-12
4374959 some_description1 file1.txt created_by Johnny D.
4374959 some_description1 image.png add_info Empty
4374959 some_description1 image.png country_id UK
1111111 text report.xls created_date 12-12-12
1111111 text image2.png created_by Sarah C.
1111111 text image2.png report_size 123123
1111111 text image3.png modified_date 13-12-12
1111111 text image3.png modified_by James B.
但我想清空重复的值并得到这样的结果:
ticket_id description file_name field_name field_value
4374959 some_description1 file1.txt created_date 12-12-12
image.png created_by Johnny D.
add_info Empty
country_id UK
1111111 text report.xls created_date 12-12-12
image2.png created_by Sarah C.
image3.png report_size 123123
modified_date 13-12-12
modified_by James B.
是否可以得到这样的结果集?
我在 AWS Athena(Presto SQL) 工作,但我真的很感谢你的 ideas/suggestions,不管 dbms。谢谢!
请注意,您不应该在 SQL 中执行此操作,因为这是表示层问题,而不是数据层问题 - 相反,您应该仅在以下位置过滤掉重复的列数据您正在渲染 HTML table 或以某种方式渲染到屏幕。
但是,如果出于某些可怕的原因您需要在 SQL 中执行此操作,则类似的方法应该可行。
- 注意重复使用显式
ORDER BY
子句以确保正确性:从不依赖隐式排序。
- 另请注意,CTE 和其他子查询不能有
ORDER BY
:只有顶级 SELECT
查询可以有 ORDER BY
子句,因此需要 ROW_NUMBER() OVER ( ORDER BY ...)
在 CTE 中。
- 我的查询使用
ticket_id
作为 description
列,因为我假设 description
是由 ticket_id
键入的,如果不是,那么您需要比较 description
直接。
- 请注意,文本比较不区分大小写,这可能是可取的,也可能不是,否则请使用显式
COLLATION
指定区分大小写的比较。
WITH t AS (
SELECT
ROW_NUMBER() OVER ( ORDER BY ticket_id, file_name, field_name ) AS n,
ticket_id,
description,
file_name,
field_name,
field_value
FROM
etc
)
SELECT
NULLIF( LAG( t.ticket_id , 1 ) OVER ( ORDER BY t.n ) = t.ticket_id, t.ticket_id ) AS ticket_id,
NULLIF( LAG( t.ticket_id , 1 ) OVER ( ORDER BY t.n ) = t.ticket_id, t.description ) AS description,
NULLIF( LAG( t.file_name , 1 ) OVER ( ORDER BY t.n ) = t.file_name, t.file_name ) AS file_name,
NULLIF( LAG( t.field_name , 1 ) OVER ( ORDER BY t.n ) = t.field_name, t.field_name ) AS field_name,
NULLIF( LAG( t.field_value, 1 ) OVER ( ORDER BY t.n ) = t.field_value, t.field_value ) AS field_value
FROM
t
ORDER BY
t.ticket_id,
t.file_name,
t.field_name
我有 3 个表:
CREATE TABLE ticket (
ticket_id int,
description varchar(1000));
CREATE TABLE document (
ticket_id int,
file_name varchar(1000));
CREATE TABLE flex_fields (
ticket_id int,
field_name varchar(1000),
field_value varchar(1000));
当我通过 ticket_id 加入这个表并查询时,我得到这样的结果:
ticket_id description file_name field_name field_value
4374959 some_description1 file1.txt created_date 12-12-12
4374959 some_description1 file1.txt created_by Johnny D.
4374959 some_description1 image.png add_info Empty
4374959 some_description1 image.png country_id UK
1111111 text report.xls created_date 12-12-12
1111111 text image2.png created_by Sarah C.
1111111 text image2.png report_size 123123
1111111 text image3.png modified_date 13-12-12
1111111 text image3.png modified_by James B.
但我想清空重复的值并得到这样的结果:
ticket_id description file_name field_name field_value
4374959 some_description1 file1.txt created_date 12-12-12
image.png created_by Johnny D.
add_info Empty
country_id UK
1111111 text report.xls created_date 12-12-12
image2.png created_by Sarah C.
image3.png report_size 123123
modified_date 13-12-12
modified_by James B.
是否可以得到这样的结果集? 我在 AWS Athena(Presto SQL) 工作,但我真的很感谢你的 ideas/suggestions,不管 dbms。谢谢!
请注意,您不应该在 SQL 中执行此操作,因为这是表示层问题,而不是数据层问题 - 相反,您应该仅在以下位置过滤掉重复的列数据您正在渲染 HTML table 或以某种方式渲染到屏幕。
但是,如果出于某些可怕的原因您需要在 SQL 中执行此操作,则类似的方法应该可行。
- 注意重复使用显式
ORDER BY
子句以确保正确性:从不依赖隐式排序。 - 另请注意,CTE 和其他子查询不能有
ORDER BY
:只有顶级SELECT
查询可以有ORDER BY
子句,因此需要ROW_NUMBER() OVER ( ORDER BY ...)
在 CTE 中。 - 我的查询使用
ticket_id
作为description
列,因为我假设description
是由ticket_id
键入的,如果不是,那么您需要比较description
直接。- 请注意,文本比较不区分大小写,这可能是可取的,也可能不是,否则请使用显式
COLLATION
指定区分大小写的比较。
- 请注意,文本比较不区分大小写,这可能是可取的,也可能不是,否则请使用显式
WITH t AS (
SELECT
ROW_NUMBER() OVER ( ORDER BY ticket_id, file_name, field_name ) AS n,
ticket_id,
description,
file_name,
field_name,
field_value
FROM
etc
)
SELECT
NULLIF( LAG( t.ticket_id , 1 ) OVER ( ORDER BY t.n ) = t.ticket_id, t.ticket_id ) AS ticket_id,
NULLIF( LAG( t.ticket_id , 1 ) OVER ( ORDER BY t.n ) = t.ticket_id, t.description ) AS description,
NULLIF( LAG( t.file_name , 1 ) OVER ( ORDER BY t.n ) = t.file_name, t.file_name ) AS file_name,
NULLIF( LAG( t.field_name , 1 ) OVER ( ORDER BY t.n ) = t.field_name, t.field_name ) AS field_name,
NULLIF( LAG( t.field_value, 1 ) OVER ( ORDER BY t.n ) = t.field_value, t.field_value ) AS field_value
FROM
t
ORDER BY
t.ticket_id,
t.file_name,
t.field_name