【问题标题】:Conditional Statement in PostgreSQL QueryPostgreSQL 查询中的条件语句
【发布时间】:2013-11-01 02:40:35
【问题描述】:

我这里有 3 个表,即:

person (
  id int PRIMARY KEY
 ,fullname text)

phonenumber (
  id int PRIMARY KEY
 ,personid int REFERENCES person(id)
 ,phonetypeid REFERENCES phonetype(id)
 ,number text)

phonetype (
 id int PRIMARY KEY
,phonetype text) -- phonetype  'Home', 'Cell', 'Fax', 'Main' etc.

每个person 可以在phonenumber 表中存储多个号码,并在phonetype 表中具有不同的电话类型:

| fullname         | number        | phonetype |
| Erwin Macale     | (671)632-3909 | Home      |
| Erwin Macale     | (671)632-3909 | Cell      |
| Erwin Macale     | (671)632-3909 | Main      |

我只想在以下条件下显示每个人的电话号码:

  • 如果他有“家庭”电话类型号码,则仅显示家庭类型删除他所有其他电话类型号码。
  • 如果他没有“家庭”号码,则只显示他的“小区”号码,然后删除他所有的其他(“传真”、“主要”等)号码。
  • 一个人可以没有电话号码。

我创建了一个临时表,其中包含名为 testablefullname, number, phonetype,然后我从这里分隔了所有电话类型号码,例如:

CREATE TEMP TABLE home AS SELECT * FROM testable WHERE phonetype ILIKE 'home';
CREATE TEMP TABLE cell AS SELECT * FROM testable WHERE phonetype ilike 'cell';
CREATE TEMP TABLE main AS SELECT * FROM testable WHERE phonetype ilike 'main';
CREATE TEMP TABLE fax AS SELECT * FROM testable WHERE phonetype ilike 'fax';
CREATE TEMP TABLE work AS SELECT * FROM testable WHERE phonetype ilike 'work';
CREATE TEMP TABLE neighbor AS SELECT * FROM testable WHERE phonetype ilike 'neighbor';
CREATE TEMP TABLE other AS SELECT * FROM testable WHERE phonetype ilike 'other';
CREATE TEMP TABLE unknown AS SELECT * FROM testable WHERE phonetype ilike 'unknown';

然后再创建一组我认为满足上述条件的临时表:

CREATE TEMP TABLE all_cell AS SELECT * FROM cell EXCEPT SELECT * FROM home;
CREATE TEMP TABLE all_main AS (SELECT * FROM main) EXCEPT (SELECT * FROM home UNION SELECT * FROM cell);
CREATE TEMP TABLE all_fax AS (SELECT * FROM fax) EXCEPT (SELECT * FROM home UNION SELECT * FROM cell UNION SELECT * FROM main);
CREATE TEMP TABLE all_work AS (SELECT * FROM work) EXCEPT (SELECT * FROM home UNION SELECT * FROM cell UNION SELECT * FROM main UNION SELECT * FROM fax);
CREATE TEMP TABLE all_neighbor AS (SELECT * FROM neighbor) EXCEPT (SELECT * FROM home UNION SELECT * FROM cell UNION SELECT * FROM main UNION SELECT * FROM fax UNION SELECT * FROM work);
CREATE TEMP TABLE all_other AS (SELECT * FROM other) EXCEPT (SELECT * FROM home UNION SELECT * FROM cell UNION SELECT * FROM main UNION SELECT * FROM fax UNION SELECT * FROM work UNION SELECT * FROM neighbor);
CREATE TEMP TABLE all_unknown AS (SELECT * FROM unknown) EXCEPT (SELECT * FROM home UNION SELECT * FROM cell UNION SELECT * FROM main UNION SELECT * FROM fax UNION SELECT * FROM work UNION SELECT * FROM neighbor UNION SELECT * FROM other);

最后选择最后一组临时表的所有并集:

SELECT fullname, number, phonetype FROM (
    SELECT * FROM home
    UNION 
    SELECT * FROM all_cell
    UNION 
    SELECT * FROM all_main
    UNION 
    SELECT * FROM all_fax
    UNION 
    SELECT * FROM all_work
    UNION 
    SELECT * FROM all_neighbor
    UNION 
    SELECT * FROM all_other
    UNION 
    SELECT * FROM all_unknown
) AS t1
ORDER BY t1.fullname, t1.phonetype;

满足我的条件的步骤正确吗? 我仍然从一个人那里得到不同的电话类型值。

【问题讨论】:

    标签: sql postgresql database-design many-to-many greatest-n-per-group


    【解决方案1】:

    您费了很多力气才得到这个单一的查询能给您带来什么:

    SELECT DISTINCT ON (p.fullname, p.id)
           p.fullname, n.number, t.phonetype
    FROM   phonenumber n 
    JOIN   person      p ON p.id = n.personid
    JOIN   phonetype   t ON t.id = n.phonetypeid
    LEFT   JOIN (
       VALUES
         (1, 'home')
        ,(2, 'cell')
        ,(3, 'main')
        ,(4, 'fax')
        ,(5, 'work')
        ,(6, 'neighbor')
        ,(7, 'other')
        ,(8, 'unknown')
       ) r(rnk, phonetype) USING (phonetype)
    ORDER  BY p.fullname, p.id, r.rnk;
    

    DISTINCT ON (p.fullname, p.id) 因为fullname 可能不是唯一的。无论如何,我都会使用它来获得您在单个查询级别中寻找的排序顺序。

    此相关答案中有关DISTINCT ON的详细信息:
    Select first row in each GROUP BY group?

    我将排名 (r.rnk) 信息附加到 VALUES expression 以使其适用于您呈现的表格布局。不过,更好的是,您将 phonetype 永久添加到表中:

    ALTER TABLE phonetype ADD COLUMN rnk int;
    
    UPDATE phonetype t
    SET    rnk = r.rnk
    FROM  (
           VALUES
             (1, 'home')
            ,(2, 'cell')
            ,(3, 'main')
            ,(4, 'fax')
            ,(5, 'work')
            ,(6, 'neighbor')
            ,(7, 'other')
            ,(8, 'unknown')
           ) r(rnk, phonetype)
    WHERE   r.phonetype = t.phonetype;
    

    然后你的查询变得更简单

    SELECT DISTINCT ON (p.fullname, p.id)
           p.fullname, n.number, t.phonetype
    FROM   phonenumber n 
    JOIN   person      p ON p.id = n.personid
    JOIN   phonetype   t ON t.id = n.phonetypeid
    ORDER  BY p.fullname, p.id, t.rnk    -- add more columns to break ties (if any)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-07
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-04
      • 2014-11-12
      相关资源
      最近更新 更多