是否可以对数据进行分组,但使用PostgreSQL将不同的值替换为@
。还是JAVA可以做得更好,更有生产力?
有些表有下一个数据
id name1 f1 f2 f3 f4 f5
1 lol 0 1 1 0 0
2 lol 0 1 1 0 0
3 lol 0 1 1 0 0
4 kek 1 1 1 1 0
5 kek 2 1 1 0 0
6 kek 4 1 1 0 0
7 kek 3 1 1 0 0
,我需要使用分组的相同数据检索名称,但是不同的数据必须以some char
的形式查看
例如:
name1 f1 f2 f3 f4 f5
lol 0 1 1 0 0
kek @ 1 1 @ 0
答案 0 :(得分:2)
SELECT
name,
CASE WHEN COUNT(DISTINCT f1) > 1 THEN '@' ELSE MAX(f1)::text END as f1,
CASE WHEN COUNT(DISTINCT f2) > 1 THEN '@' ELSE MAX(f2)::text END as f2,
CASE WHEN COUNT(DISTINCT f3) > 1 THEN '@' ELSE MAX(f3)::text END as f3,
CASE WHEN COUNT(DISTINCT f4) > 1 THEN '@' ELSE MAX(f4)::text END as f4,
CASE WHEN COUNT(DISTINCT f5) > 1 THEN '@' ELSE MAX(f5)::text END as f5
FROM
my_table
GROUP BY name
对于每一列:
COUNT(DISTINCT)
计算不同的值GROUP BY
引起的聚合函数。最简单的方法是采用MAX
或MIN
,所以没关系-只有一个值)。由于添加了text
类型的值,因此所有其他值都必须转换为同一列类型,因为不允许在一列中获取更多类型。因此,如果您确实有integer
值,则最好也将integer
值用作您的“标记”值。如果您没有任何负值或类似的值,则负值也许可以做到。答案 1 :(得分:1)
使用子查询时,您可以尝试使用大小写。
CREATE TABLE T(
name1 varchar(50),
f1 int,
f2 int,
f3 int,
f4 int,
f5 int
);
INSERT INTO T VALUES ('lol',0,1,1,0,0);
INSERT INTO T VALUES ('lol',0,1,1,0,0);
INSERT INTO T VALUES ('lol',0,1,1,0,0);
INSERT INTO T VALUES ('kek',1,1,1,1,0);
INSERT INTO T VALUES ('kek',2,1,1,0,0);
INSERT INTO T VALUES ('kek',4,1,1,0,0);
INSERT INTO T VALUES ('kek',3,1,1,0,0);
查询1 :
SELECT distinct
name1,
CASE WHEN
(SELECT COUNT(DISTINCT f1) cnt
FROM T tt
WHERE t1.name1 = tt.name1) > 1 THEN '@' ELSE t1.f1::VARCHAR(50) END,
CASE WHEN
(SELECT COUNT(DISTINCT f2) cnt
FROM T tt
WHERE t1.name1 = tt.name1) > 1 THEN '@' ELSE t1.f2::VARCHAR(50) END,
CASE WHEN
(SELECT COUNT(DISTINCT f3) cnt
FROM T tt
WHERE t1.name1 = tt.name1) > 1 THEN '@' ELSE t1.f3::VARCHAR(50) END,
CASE WHEN
(SELECT COUNT(DISTINCT f4) cnt
FROM T tt
WHERE t1.name1 = tt.name1) > 1 THEN '@' ELSE t1.f4::VARCHAR(50) END,
CASE WHEN
(SELECT COUNT(DISTINCT f5) cnt
FROM T tt
WHERE t1.name1 = tt.name1) > 1 THEN '@' ELSE t1.f5::VARCHAR(50) END
FROM T t1
Results :
| name1 | f1 | f2 | f3 | f4 | f5 |
|-------|----|----|----|----|----|
| kek | @ | 1 | 1 | @ | 0 |
| lol | 0 | 1 | 1 | 0 | 0 |
答案 2 :(得分:1)
此处无需子查询。您可以使用GROUP
在单个查询中进行操作。看看:
SELECT
name1,
CASE WHEN array_length(array_agg(DISTINCT f1), 1) = 1 THEN min(f1)::text ELSE '@' END AS f1,
CASE WHEN array_length(array_agg(DISTINCT f2), 1) = 1 THEN min(f2)::text ELSE '@' END AS f2,
CASE WHEN array_length(array_agg(DISTINCT f3), 1) = 1 THEN min(f3)::text ELSE '@' END AS f3,
CASE WHEN array_length(array_agg(DISTINCT f4), 1) = 1 THEN min(f4)::text ELSE '@' END AS f4,
CASE WHEN array_length(array_agg(DISTINCT f5), 1) = 1 THEN min(f5)::text ELSE '@' END AS f5
FROM T
GROUP BY name1;
这是怎么回事:
name1
分组array_agg
函数将返回给定字段的属性数组DISTINCT
子句删除array_length
函数返回数组中的元素数。由于数组没有重复项,因此它是唯一元素的数量。CASE
语句格式化结果。如果数组具有1个元素,则将其显示(转换为文本)。否则,将显示@
。