SQL GROUP BY和之后的返回类型

SQL GROUP BY和之后的返回类型,sql,postgresql,group-by,reduce,Sql,Postgresql,Group By,Reduce,我正在使用PostgreSQL v.11。我有一个有三列的表。我的目标是找到数据内部的冗余 首先,我做了一个简单的分组: SELECT client, block, "date" FROM lines GROUP BY client, block, "date" ORDER BY client, block 结果如下所示: 1 | P10001 | 2020-01-01 1 | P10002 | 2020-04-17 1 | P10002 | 2020-

我正在使用PostgreSQL v.11。我有一个有三列的表。我的目标是找到数据内部的冗余

首先,我做了一个简单的分组:

SELECT client, block, "date"
FROM lines
GROUP BY client, block, "date"
ORDER BY client, block
结果如下所示:

1 | P10001 | 2020-01-01
1 | P10002 | 2020-04-17
1 | P10002 | 2020-05-04
1 | P10003 | 2020-05-05
现在,我想确定具有相同块但不同日期的行。在本例中,第2行和第3行block=P10002就是这种情况

现在,我使用javascript解析完整的resultset,并找到我使用result.reduce的这两个冗余行

但是,在纯SQL中,有没有一种方法可以提取这个重新导出的结果呢

预期结果如下:

1 | P10002 | 2020-04-17
1 | P10002 | 2020-05-04
在resultset中保留这两个日期应该很好,因为我只需要为其中一个更改块。如果结果集中没有日期列,则需要执行第二个请求以查找所有受影响的行

下面是表和数据的脚本

CREATE TABLE lines (
  "client" integer NOT NULL,
  "block" text NOT NULL,
  "date" date NOT NULL
);

INSERT INTO lines ("client", "block", "date") VALUES
  (1, 'P10001', '2020-01-01'),
  (1, 'P10002', '2020-04-17'),
  (1, 'P10002', '2020-05-04'),
  (1, 'P10003', '2020-05-05');
非常感谢

您可以使用HAVING子句和按块分组来清楚地计算日期:


这适用于所有数据库管理系统

一些未指定的DBMS还提供分组汇总。在数据库管理系统的文档中查找

如前所述,这一方法适用于任何地方——它们可能会以不同的方式对null进行排序

WITH
lines(client,block,dt) AS (
          SELECT 1,'P10001',DATE '2020-01-01'
UNION ALL SELECT 1,'P10002',DATE '2020-04-17'
UNION ALL SELECT 1,'P10002',DATE '2020-05-04'
UNION ALL SELECT 1,'P10003',DATE '2020-05-05'
UNION ALL SELECT 1,'P10001',DATE '2020-01-01'
UNION ALL SELECT 1,'P10002',DATE '2020-04-17'
UNION ALL SELECT 1,'P10002',DATE '2020-05-04'
UNION ALL SELECT 1,'P10003',DATE '2020-05-05'
)
SELECT
  client
, block
, dt
FROM lines
UNION ALL
SELECT
  client
, block
, NULL::DATE AS dt
FROM lines
GROUP BY
  client
, block
ORDER BY
  client
, block
, dt
-- out  client | block  |     dt     
-- out --------+--------+------------
-- out       1 | P10001 | 
-- out       1 | P10001 | 2020-01-01
-- out       1 | P10001 | 2020-01-01
-- out       1 | P10002 | 
-- out       1 | P10002 | 2020-04-17
-- out       1 | P10002 | 2020-04-17
-- out       1 | P10002 | 2020-05-04
-- out       1 | P10002 | 2020-05-04
-- out       1 | P10003 | 
-- out       1 | P10003 | 2020-05-05
-- out       1 | P10003 | 2020-05-05
您应该使用having子句来获取冗余数据集。我假设在冗余检测中也需要客户端

查询如下所示

SELECT client, block
FROM lines
GROUP BY client, block
HAVING count(distinct "date") > 1
ORDER BY client, block
您可以通过以下方式执行此操作:

看。 结果:


那么,您想要的输出到底是什么呢?我正在使用PostgreSQL v11Cool,它似乎可以工作!如果表中有数百万行,您知道与分组解决方案相比,是否存在性能成本吗?如果您使用分组方式。。。除非您将其用作另一个select语句的子查询,否则您不会得到完整的行,而只能得到client、block。那你需要什么?带日期的整行还是仅客户端、块?关于性能,您必须对其进行测试。EXISTS执行得非常快,因为它不必扫描while表,但只要找到匹配项就会返回。如果每个客户机没有重复日期的情况,block如果您感兴趣,还有一个带有窗口功能的解决方案。我需要的是客户机,block,按客户机分组的日期,block,但仅适用于具有多个日期的组。在那之后,我需要更改块,因为同一个块不能有多个日期在包含GROUP BY client,block的语句中,您不会在包含所有不同日期的结果client,block,date中得到结果。你只得到了client,block。在进一步挖掘之后,你的答案肯定是我需要的答案,非常感谢。这个解决方案也非常有趣,如果我们在select子句中添加MAXdate,它会像预期的那样工作。您知道与forpas解决方案相比是否存在性能成本吗?在forpas EXISTS解决方案中,我看到了一个潜在的性能问题,因为它执行自连接,当表较大时,这可能会带来成本。另一个分区为的解决方案可能不适用于所有DBMS。谢谢。事实上,你们两个给出了适合我需要的答案。现在,forpas更快,我只访问一个DB。有了你们的团队,在大桌子上可能会更好,这不是我的情况。。。现在;-我肯定会记住这两个答案。谢谢!
SELECT client, block
FROM lines
GROUP BY client, block
HAVING count(distinct "date") > 1
ORDER BY client, block
select l.* from lines l
where exists (
  select 1 from lines
  where client = l.client and block = l.block and date <> l.date
)
select client, block, date
from (
  select *, count(*) over (partition by client, block) counter
  from lines
) t
where counter > 1
> client | block  | date      
> -----: | :----- | :---------
>      1 | P10002 | 2020-04-17
>      1 | P10002 | 2020-05-04