比较与所有记录匹配的行和返回列(POSTGRESQL)

时间:2016-11-18 06:05:00

标签: sql database postgresql join

我有一张桌子(tbl_customer)

id | name   | birthday | address  | gender
-------------------------------------------
1  | JOSEPH | 19920413 | NEW YORK | M
2  | JAKE   | 19920413 | LONDON   | M
3  | JOHN   | 19920413 | GERMANY  | M

然后我需要一个查询来比较该表中的所有记录,然后返回与所有记录相同的列。对于上面的例子,结果应该是:

 birthday | gender
-------------------
 19920413 | M
 19920413 | M
 19920413 | M

或者如果结果看起来像这样的话要好得多......

 column_name | value
--------------------------
 birthday    | 19920413 
 gender      | M

谢谢:)

3 个答案:

答案 0 :(得分:1)

使用hstore扩展程序和plpgsql

create function foo(out f_name text, out f_value text) returns setof record language plpgsql immutable as $$
declare
  h hstore;
  r hstore := null;
  n text[];
begin
  for h in select hstore(t.*) from tbl_customer as t loop
    if r is null then
      r := h;
    else
      /* -- To ignore NULLs so the null values does not affects to the result
      select array_agg(key) into n from each(r) where value is null;
      r := r || coalesce(slice(h, n), '');
      select array_agg(key) into n from each(h) where value is null;
      h := h || coalesce(slice(r, n), '');
      */ -- I believe that there is much more elegant solution is possible 
      r := r - akeys(r - h);
      exit when r = '';
    end if;
  end loop;
  raise info '%', r;
  return query select * from each(r);
end $$;

select * from foo();

INFO:  "gender"=>"M", "birthday"=>"19920413"
╔══════════╤══════════╗
║  f_name  │ f_value  ║
╠══════════╪══════════╣
║ gender   │ M        ║
║ birthday │ 19920413 ║
╚══════════╧══════════╝

答案 1 :(得分:1)

静态代码解决方案

select      (array ['id','name','birthday','address','gender'])[pos] as column_name
           ,min(val)                                                 as value

from        t cross join
              unnest(array [id::varchar(10),name,birthday::varchar(10),address,gender]) with ordinality u(val,pos)

group by    pos

having      (   count (distinct val) = 1
            and count(*) = count (val)
            )
        or  count (val) = 0

答案 2 :(得分:-2)

select * 
from tbl_customer 
where birthday in (
    select birthday 
    from tbl_customer 
    group by birthday 
    having count(*) > 1
)