我这里有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 |
我只想显示符合以下条件的每个人的电话号码:
我创建了一个临时表,其中包含名为fullname, number, phonetype
的{{1}},然后从这里我将所有的类型数字分开,如:
testable
然后创建另一组临时表,我认为满足上述条件:
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);
满足我条件的步骤是否正确? 我仍然从一个人那里获得不同的语音值。
答案 0 :(得分:3)
为了获得这个单一查询可以提供的内容,您遇到了很多麻烦:
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?
我使用VALUES
expression添加了排名(r.rnk
)信息,以使其与您呈现的表格布局配合使用。但是,更好的是,您永久地添加到表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)