SQL选择第一,第二,第三,第四,最后

时间:2014-06-03 04:10:26

标签: sql database select group-by

我有一个会员数据库,其中有一些人居住在同一地址。为了尽量减少邮寄新闻通讯时的邮政支出,我想从数据库中选择唯一的地址,并在同一地址的人的同一标签上添加所有名称。我在Members表格中的字段为NamesAddressLine1AddressLine2SuburbStatePostcode

我很高兴创建一个新表,例如,如果需要,可以添加名为FirstOfNameSecondOfNamesThirdOfNamesLastOfNames的其他字段。生活在我的数据库中相同地址的最大人数是5。

标签上所需输出的示例:

John Smith

Jane Smith

10 High Street

Beverly Hills, NSW 2000

我非常感谢任何帮助,因为我在这方面遇到很多困难。

谢谢堆, 米卡

1 个答案:

答案 0 :(得分:0)

我认为您理想的目标是在单个复杂查询中获得最多五个名称和一个地址。这个例子在PostgreSQL中。您没有指定数据库,但我相信ORACLE和SQLServer中存在推论。你必须自己做适应。

它有点乱,但它有效。简而言之,您使用WINDOW函数对每个唯一地址的多个名称进行排名。使用WITH子句按等级隔离每个名称。 LEFT JOIN为少于五个名称的地址选择名称。

样本表:

   DROP TABLE name_address;

   CREATE TABLE name_address
   (
   first_name CHARACTER VARYING (50)
   ,last_name CHARACTER VARYING (50)
   ,addr_line1 CHARACTER VARYING (50)
   ,city CHARACTER VARYING (50)
   ,state CHARACTER VARYING (2)
   ,zip  CHARACTER VARYING (5)
   )
   WITH (OIDS=TRUE);
   ALTER TABLE name_address OWNER TO your_name_here;

示例数据:

   INSERT INTO name_address (first_name, last_name, addr_line1, city, state, zip) SELECT 'John', 'Smith', '10 High Street', 'Beverly Hills NSW 2000', 'CA', '90210';
   INSERT INTO name_address (first_name, last_name, addr_line1, city, state, zip) SELECT 'Jane', 'Smith', '10 High Street', 'Beverly Hills NSW 2000', 'CA', '90210';
   INSERT INTO name_address (first_name, last_name, addr_line1, city, state, zip) SELECT 'Jeff', 'Smith', '12 High Street', 'Beverly Hills NSW 2000', 'CA', '90210';
   INSERT INTO name_address (first_name, last_name, addr_line1, city, state, zip) SELECT 'Jean', 'Smith', '12 High Street', 'Beverly Hills NSW 2000', 'CA', '90210';
   INSERT INTO name_address (first_name, last_name, addr_line1, city, state, zip) SELECT 'Jenn', 'Smith', '12 High Street', 'Beverly Hills NSW 2000', 'CA', '90210';
   INSERT INTO name_address (first_name, last_name, addr_line1, city, state, zip) SELECT 'Jack', 'Smith', '12 High Street', 'Beverly Hills NSW 2000', 'CA', '90210';
   INSERT INTO name_address (first_name, last_name, addr_line1, city, state, zip) SELECT 'Josh', 'Smith', '12 High Street', 'Beverly Hills NSW 2000', 'CA', '90210';

解决方案:

   WITH nr AS (SELECT DISTINCT first_name, last_name, addr_line1, city, state, zip, COUNT(*) OVER(PARTITION BY zip, state, city, addr_line1 ORDER BY zip, state, city, addr_line1, last_name, first_name) AS name_rank
   FROM name_address
   GROUP BY first_name, last_name, addr_line1, city, state, zip
   ORDER BY zip, state, city, addr_line1, name_rank)
   ,n1 AS(SELECT nr.first_name, nr.last_name, nr.addr_line1, nr.city, nr.state, nr.zip
   FROM nr
   WHERE nr.name_rank = 1)
   ,n2 AS(SELECT nr.first_name, nr.last_name, nr.addr_line1, nr.city, nr.state, nr.zip
   FROM nr
   WHERE nr.name_rank = 2)
   ,n3 AS(SELECT nr.first_name, nr.last_name, nr.addr_line1, nr.city, nr.state, nr.zip
   FROM nr
   WHERE nr.name_rank = 3)
   ,n4 AS(SELECT nr.first_name, nr.last_name, nr.addr_line1, nr.city, nr.state, nr.zip
   FROM nr
   WHERE nr.name_rank = 4)
   ,n5 AS(SELECT nr.first_name, nr.last_name, nr.addr_line1, nr.city, nr.state, nr.zip
   FROM nr
   WHERE nr.name_rank = 5)
   SELECT   DISTINCT n1.first_name
       , n1.last_name
       , n2.first_name
       , n2.last_name
       , n3.first_name
       , n3.last_name
       , n4.first_name
       , n4.last_name
       , n5.first_name
       , n5.last_name
       , na.addr_line1
       , na.city
       , na.state
       , na.zip
   FROM name_address AS na
   LEFT JOIN n1 ON n1.addr_line1 = na.addr_line1 AND n1.city = na.city AND n1.state = na.state AND n1.zip = na.zip
   LEFT JOIN n2 ON n2.addr_line1 = na.addr_line1 AND n2.city = na.city AND n2.state = na.state AND n2.zip = na.zip
   LEFT JOIN n3 ON n3.addr_line1 = na.addr_line1 AND n3.city = na.city AND n3.state = na.state AND n3.zip = na.zip
   LEFT JOIN n4 ON n4.addr_line1 = na.addr_line1 AND n4.city = na.city AND n4.state = na.state AND n4.zip = na.zip
   LEFT JOIN n5 ON n5.addr_line1 = na.addr_line1 AND n5.city = na.city AND n5.state = na.state AND n5.zip = na.zip;

这是最终输出:

“简”;“史密斯”;“约翰”;“史密斯”;“”;“”;“”;“”;“”;“”“;”10 High Street“;”Beverly Hills NSW 2000“; “CA”, “90210” “杰克”;“史密斯”;“吉恩”;“史密斯”;“杰夫”;“史密斯”;“詹恩”;“史密斯”;“乔什”;“史密斯”;“12大街”;“比佛利山庄” 2000 “” CA “” 90210"