0

我现在正在处理 Polarion 小部件的 SQL 查询,我想在其中获取带有未解决评论的项目。不幸的是,我在加入三个表时遇到问题,其中一个表有可选的空/空。Polarion 中有几个不同的表格来包含评论,其中大部分都有已解决的状态。我正在使用WORKITEM、COMMENT、MODULECOMMENT表,因为有时 workitem 在这里有评论,有时在另一个表中。

区别一:当workitem有“正常”注释时,COMMENT表中总是有FK键,但不是每个workitem都有FK MODULE键(表结构)。

在默认小部件中,我可以使用 SQL 查询,但有一个很大的限制: 我不能替换整个selectfrom,因为有一条静态行:SELECT WORKITEM.C_URIFROM WORKITEM,所以我只能添加一些东西(我试过DISTINCT ON,但你怎么看,我不能替换那行)

Polarion 也有另一个问题,每个文档都有标题、文本等,并且每个元素都是具有相同FK_URI_MODULE的单独工作项(并且文档使用MODULECOMMENT表)。

我想从 MODULECOMMENT 中删除重复项(忽略 workitem.FK_URI_MODULE 为空/空的情况,因为它是正常状态)。

我创造的最好的,它就在这里(在这种情况下,我将is null替换为is not null,因为它返回的项目更少):

select workitem.c_uri, workitem.FK_URI_MODULE
from workitem 
left join COMMENT on COMMENT.FK_URI_WORKITEM = WORKITEM.C_URI 
left join MODULECOMMENT on MODULECOMMENT.FK_URI_MODULE = WORKITEM.FK_URI_MODULE 
where true
and workitem.fk_uri_project = 231 
and (comment.c_resolved is not null 
or modulecomment.c_resolved is not null);

和我的结果:

c_uri  | fk_uri_module
--------+---------------
   7952 |          7940
   7949 |          7940
   7953 |          7940
   7964 |          7940
 124141 |        124138
    609 |
   1347 |
    609 |

但我想得到这样的东西:

c_uri  | fk_uri_module
--------+---------------
   7952 |          7940
 124141 |        124138
    609 |
   1347 |
    609 |
4

2 回答 2

1

不要通过不加入而是使用 EXISTS 条件来生成重复项:

select workitem.c_uri, workitem.fk_uri_module
from workitem 
where exists (select * 
              from comment 
                left join modulecomment on modulecomment.fk_uri_module = workitem.fk_uri_module 
              where comment.fk_uri_workitem = workitem.c_uri
                and (comment.c_resolved is not null 
                     or modulecomment.c_resolved is not null))
where workitem.fk_uri_project = 231 
于 2021-02-25T10:15:11.250 回答
0

You can use DISTINCT ON for this, which returns only the first record of a group:

demos:db<>fiddle

select DISTINCT ON (workitem.FK_URI_MODULE) 

    workitem.c_uri, workitem.FK_URI_MODULE
from workitem 
left join COMMENT on COMMENT.FK_URI_WORKITEM = WORKITEM.C_URI 
left join MODULECOMMENT on MODULECOMMENT.FK_URI_MODULE = WORKITEM.FK_URI_MODULE 
where true
    and workitem.fk_uri_project = 231 
    and (comment.c_resolved is not null 
    or modulecomment.c_resolved is not null)

The interesting part is the NULL records. The query above returns only one of the NULL records, because DISTINCT ON also removes duplicates for NULL.

So, if you want to keep all NULL values, we need to treat the NULL records differently:

SELECT DISTINCT ON (fk_uri_module)  -- 1
    *
FROM <your_query>
WHERE fk_uri_module IS NOT NULL

UNION ALL

SELECT                              -- 2
    *
FROM <your_query>
WHERE fk_uri_module IS NULL
  1. Apply DISTINCT ON on all records with non-NULL values
  2. UNION ALL records with NULL afterwards

To avoid executing your entire query twice, you can move them into a CTE (WITH clause) and reference it later:

WITH my_result AS (
    -- <your_query>
)
SELECT DISTINCT ON (fk_uri_module)
    *
FROM my_result 
WHERE fk_uri_module IS NOT NULL

UNION ALL

SELECT
    *
FROM my_result 
WHERE fk_uri_module IS NULL

Edit:

demo:db<>fiddle

If you cannot use DISTINCT ON, a valid alternative for this is the row_number() window function:

SELECT
    *
FROM (
    select
        workitem.c_uri, workitem.FK_URI_MODULE,
    
        row_number() OVER (PARTITION BY workitem.FK_URI_MODULE)

    from workitem 
    left join COMMENT on COMMENT.FK_URI_WORKITEM = WORKITEM.C_URI 
    left join MODULECOMMENT on MODULECOMMENT.FK_URI_MODULE = WORKITEM.FK_URI_MODULE 
    where true
        and workitem.fk_uri_project = 231 
        and (comment.c_resolved is not null 
        or modulecomment.c_resolved is not null)
) s
WHERE row_number = 1
于 2021-02-25T08:32:12.393 回答