【问题标题】:Select Distinct with CASE - PostgreSQL选择与 CASE 不同 - PostgreSQL
【发布时间】:2014-12-19 00:23:45
【问题描述】:

我正在尝试从不同的表格中选择地点信息:我将地点放在一张桌子上,地理坐标放在另一张桌子上,电话和电子邮件放在另一张桌子上。问题是我们可能有也可能没有电子邮件和电话。我正在寻找一种在电子邮件/电话存在时获取它们的方法,如果它们不知道则具有空白值。所以我在 SELECT 上使用了“CASE”指令。

如果我们没有电子邮件也没有电话,一切都会好起来的:我们只返回了一行。

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

  1. 地名,空白电话,空白邮件
  2. 地名、空白电话、填充邮件
  3. 地名,电话号码,空白邮件

我正在寻找一种只得到一行的方法:

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

我尝试了'distinct',但没有成功:(

这是我的查询:

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”被返回了 3 次,因为它同时包含电话号码和电子邮件,而“Les cabanes”只返回了一次,因为它没有任何信息。

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

【问题讨论】:

    标签: postgresql select case distinct


    【解决方案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

    【讨论】:

    • 我愿意拥有所有的地方,只要有电子邮件和电话;我会试试你的想法,谢谢
    • 作为第一次测试,它只返回空白邮件和电话
    • 抱歉,添加“gen”。在从“电话”和“电子邮件”中,我把它误认为是别名,但事实并非如此。答案已修改。
    【解决方案2】:

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

    (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
    

    来自
    地点

    【讨论】:

      【解决方案3】:

      我想你可以试试这个来获取所有的电子邮件和电话号码

      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
      

      【讨论】:

        猜你喜欢
        • 2016-06-26
        • 1970-01-01
        • 1970-01-01
        • 2018-01-11
        • 2020-09-23
        • 2013-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多