选择Distinct with CASE - PostgreSQL

时间:2014-10-23 10:40:08

标签: postgresql select case distinct

我正在尝试从不同的表中选择地点信息:我在一个表中有位置,在另一个表中有地理坐标,在另一个表中有电话和电子邮件。问题是我们可能有或没有电子邮件和电话。我正在寻找一种方法来获取电子邮件/电话,如果它们不存在则会显示空白值。所以我使用" CASE"有关SELECT的说明。

如果我们没有电子邮件,也没有电话,一切顺利:我们只返回一行。

但如果我们有电子邮件或电话,它会返回2行;最糟糕的情况是我们同时拥有电子邮件和电话:在这种情况下,它会为每个地方返回三行:

  1. 地名,空白电话,空白邮件
  2. 地名,空白电话,填充邮件
  3. 地名,填充电话,空白邮件
  4. 我正在寻找一种只获得一条线的方法:

    0)地名+填充(或不填写)电话+填充(或不填写)邮件

    我尝试了“不同的”'但它没有做到这一点:(

    这是我的问题:

    select distinct
        places.name     as place,
    
        CASE place_properties.pkey      WHEN    'gen.telephone' 
                                        THEN    place_properties.pvalue
                                        END 
                                        as  telephone,
    
        CASE place_properties.pkey      WHEN    'gen.email' 
                                        THEN    place_properties.pvalue
                                        END 
                                        as  email
    from     
        places
    inner join
        place_properties   on place_properties.place_id     = places.id
    

    这是一个简化的答案示例:

    "ALLIAT"                ;"0561059858"   ;""
    "ALLIAT"                ;""             ;"contact@leslonguespistes.com"
    "ALLIAT"                ;""             ;""
    "TARASCON SUR ARIEGE"   ;"0561023281"   ;""
    "TARASCON SUR ARIEGE"   ;""             ;"hotel@manoiragnes.com"
    "TARASCON SUR ARIEGE"   ;""             ;""
    "Les Cabanes"           ;""             ;""
    

    我们看到' ALLIAT'和Tarascon'三次返回,因为它有电话号码和电子邮件,而#34; Les cabanes"只返回一次,因为它没有任何一个。

    当我们在数据库中使用电子邮件和/或电话时,如何将SQL更改为只有一行?

3 个答案:

答案 0 :(得分:1)

试试这个:

SELECT
      places.name AS place
    , pp.telephone
    , pp.email
FROM places
      LEFT JOIN (
                  SELECT
                        place_id
                      , MAX(CASE place_properties.pkey WHEN 'gen.telephone' THEN place_properties.pvalue END) AS telephone
                      , MAX(CASE place_properties.pkey WHEN 'gen.email' THEN place_properties.pvalue END)     AS email
                  FROM place_properties
                  WHERE place_properties.pkey IN ('gen.telephone', 'gen.email')
                  GROUP BY
                        place_id
            ) AS pp
                  ON places.id = pp.place_id

有可能使用这种方法的替代方法,但为此我建议我们需要一组好的样本数据。


目前尚不清楚您是否只想要有电话号码的地方,所以我使用了LEFT JOIN来列出所有地点。如果您只想要那些地方(电话或电子邮件),请使用INNER JOIN代替

答案 1 :(得分:1)

我认为您可以尝试使用此功能获取所有电子邮件和电话号码

SELECT places.name AS place,
       pp.telephone
       pp.email
  FROM places
  LEFT JOIN (
                  SELECT
                        place_id, 
                        ARRAY_TO_STRING(ARRAY_AGG(DISTINCT NULLIF(CASE place_properties.pkey WHEN 'gen.telephone' THEN place_properties.pvalue END,'')),',') AS telephone,
                        ARRAY_TO_STRING(ARRAY_AGG(DISTINCT NULLIF(CASE place_properties.pkey WHEN 'gen.email' THEN place_properties.pvalue END,'')),',') AS email
                  FROM place_properties
                  WHERE place_properties.pkey IN ('gen.telephone', 'gen.email')
                  GROUP BY 1
            ) AS pp
                  ON places.id = pp.place_id

答案 2 :(得分:0)

您可以在此处使用子选项,例如:select     以地名命名,

(select pvalue from place_properties where pkey = 'gen.telephone' and place_properties.place_id     = places.id)                          as  telephone,

(select pvalue from place_properties where pkey = 'gen.email' and place_properties.place_id     = places.id)                          as  email


    地方