【问题标题】:SQL problem - one name 2 address in the same tableSQL问题——同一张表中一个名字2地址
【发布时间】:2023-04-01 05:46:01
【问题描述】:
CName           |   AddressLine
-------------------------------
John Smith      | 123 Nowheresville
Jane Doe        | 456 Evergreen Terrace
John Smith      | 999 Somewhereelse
Joe Bloggs      | 1 Second Ave

如果我有这张表,可以选择这样放置

CNAME      | Address1           | Address2

John Smith | 123 Nowheresville  | 999 Somewhereelse

我正在使用甲骨文

【问题讨论】:

  • @user - 每个CName 最多有 2 个地址行吗?另外你怎么知道哪个是 1 哪个是 2 或者这是任意的?
  • 首先你怎么确定他们不是两个不同的人?名称不是唯一的。通常姓名和地址会正确存储在相关表中,因此人们可以有多个地址。
  • 如果您有预设数量的地址,您可以自行加入与该数量一样多的次数。如果你不知道那个号码,那么 www.mongodb.org
  • 他们总是 2。如果我使用自我加入,它会工作吗?
  • @chx:或者你可以,你知道,正确规范地址数据。仅仅因为您不知道用户的地址数量而切换到 NoSql?来吧。

标签: sql oracle


【解决方案1】:

问题解决了,oracle 论坛的 Frank Kulash 解决了问题

解决办法如下:

WITH got_r_num  AS
(
    SELECT  cname, addressline
    ,   ROW_NUMBER () OVER ( PARTITION BY  cname
                         ORDER BY      addressline
                   )       AS r_num
    FROM    table_x
--  WHERE   ...     -- If you need any filtering, put it here
)
SELECT    cname
,     MIN (CASE WHEN r_num = 1 THEN addressline END)    AS addressline1
,     MIN (CASE WHEN r_num = 2 THEN addressline END)    AS addressline2
FROM      got_r_num
GROUP BY  cname

感谢大家的帮助

【讨论】:

    【解决方案2】:

    就您的表格而言,您不能使用简单的自联接将其减少为一行。您可以恢复包含所有地址的行(只要您硬编码特定的最大地址数),但您将始终拥有与给定用户的地址相同的行数(除非您有一种将单个地址标识为“主要”的方法)。

    为了将您的结果集减少到一行,您必须提供一些标记“第一个”地址的方法。使用 SQL Server(或类似的专业级 RDBM),您可以使用具有排名/行编号功能的公用表表达式来执行此操作:

    with Addresses as
    (select 
        CName, 
        AddressLine, 
        row_number() over (partition by CName order by AddressLine) as RowNum
    
    from YourTable)
    select
        a1.CName,
        a1.AddressLine as Address1,
        a2.AddressLine as Address2,
        a3.AddressLine as Address3
    
    from Addresses a1
    
    left join Addresses a2 on a2.CName = a1.CName and a2.RowNum = 2
    left join Addresses a3 on a3.CName = a1.CName and a3.RowNum = 3
    
    where a1.RowNum = 1
    

    【讨论】:

    • @macwadu:你从来没有告诉我们你使用的是哪个数据库系统。
    • 对不起,我用的是oracle
    【解决方案3】:

    仅在某些行中添加新列以显示重复被认为是一种糟糕的设计(内存使用效率低下)。也许您应该考虑使用内部连接和一个单独的表作为地址列!

    【讨论】:

      【解决方案4】:

      temp = 你的表名

      select distinct cname, addressline as [address1],
      ( 
      ISNULL((select addressline from temp where cname = t.cname and addressline != t.addressline), '')
      ) as address2
      from
      temp t
      

      【讨论】:

      • 这将为组合返回 2 条记录,例如 name, a1, a2 和 name, a2, a1
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多