Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 乱七八糟的桌子_Sql Server - Fatal编程技术网

Sql server 乱七八糟的桌子

Sql server 乱七八糟的桌子,sql-server,Sql Server,我在SQL Server中有一个凌乱的表(对不起,这是我从供应商那里得到它的方式)。我已经把它大大简化了,这样我就可以集中精力解决这个问题,尽管我显然已经看不见森林了 目标:虽然我似乎无法得到正确的逻辑,但有点取消了这些数据。 问题:奇怪的是,我需要列标题的子字符串作为数据的一部分-如下面的示例所示 Rextester示例数据 导入后,我的表如下所示: +----+----------+--------------------+--------------------+-------------

我在SQL Server中有一个凌乱的表(对不起,这是我从供应商那里得到它的方式)。我已经把它大大简化了,这样我就可以集中精力解决这个问题,尽管我显然已经看不见森林了

目标:虽然我似乎无法得到正确的逻辑,但有点取消了这些数据。
问题:奇怪的是,我需要列标题的子字符串作为数据的一部分-如下面的示例所示

Rextester示例数据

导入后,我的表如下所示:

+----+----------+--------------------+--------------------+-------------------+-------------------+
| id |  person  | contact 1 - phone  | contact 2 - phone  | contact 1 - email | contact 2 - email |
+----+----------+--------------------+--------------------+-------------------+-------------------+
|  1 | john doe |             123456 |             234567 | john@doe.me       | johndoe@gmail.com |
|  2 | jane doe |             654321 |             765432 | Jane@doe.me       | NULL              |
+----+----------+--------------------+--------------------+-------------------+-------------------+
预期产出:

+----+----------+---------------+--------+-------------------+
| id |  person  | contactNumber | phone  |       email       |
+----+----------+---------------+--------+-------------------+
|  1 | John Doe |             1 | 123456 | john@doe.me       |
|  1 | John Doe |             2 | 234567 | johndoe@gmail.com |
|  2 | Jane Doe |             1 | 654321 | jane@doe.me       |
|  2 | Jane Doe |             2 | 765432 | janedoe@gmail.com |
+----+----------+---------------+--------+-------------------+

如果联系人2的电子邮件或电话不为空,您可以使用
UNION
生成联系人1的所有记录和联系人2的所有记录。如果contact-2的电子邮件为空,则使用
COALESCE
使用contact-1的电子邮件

SELECT id, person, 1 [contactNumber], [contact 1 - phone] [phone], [contact 1 - email] [email]
FROM #TEST

UNION

SELECT id, person, 2
  , [contact 2 - phone]
  , COALESCE([contact 2 - email], [contact 1 - email])
FROM #TEST
WHERE [contact 2 - phone] IS NOT NULL OR [contact 2 - email] IS NOT NULL
你试过这个吗

SELECT 
    id, 
    person,
    1 as contactnumber, 
    [contact 1 - phone] as phone, 
    [contact 1 - email] as email 
FROM Table
UNION
SELECT 
    id, 
    person,
    2 as contactnumber, 
    [contact 2 - phone] as phone, 
    [contact 2 - email] as email 
FROM Table

以防你需要“动态”,也就是说,你不知道专栏(或联系人)如何

示例

Declare @YourTable Table ([id] varchar(50),[person] varchar(50),[contact 1 - phone] varchar(50),[contact 2 - phone] varchar(50),[contact 1 - email] varchar(50),[contact 2 - email] varchar(50))
Insert Into @YourTable Values 
 (1,'john doe',123456,234567,'john@doe.me','johndoe@gmail.com')
,(2,'jane doe',654321,765432,'Jane@doe.me',NULL)


Select id
      ,person
      ,contactNumber
      ,phone  = max(case when Item like '%phone%' then value end)
      ,email  = max(case when Item like '%email%' then value end)
 From (
        Select A.ID
              ,A.Person
              ,contactNumber = cast(substring(Item,patindex('%[0-9]%',item),2) as int)
              ,C.*
         From @YourTable A
         Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
         Cross Apply (
                        Select Item  = replace(a.value('local-name(.)','varchar(100)'),'_x0020_',' ')
                              ,Value = a.value('.','varchar(max)') 
                         From  B.XMLData.nodes('/row')  as C1(n)
                         Cross Apply C1.n.nodes('./@*') as C2(a)
                         Where a.value('local-name(.)','varchar(100)') not in ('id','person')
                     ) C
      )  A
 Group By id,person,contactNumber
返回

编辑-简化

返回


您忘记了从句a中的答案,因此,它基本上与我的答案相同。从句a中,我希望联系人2出现,但如果没有,我希望为空-联合会再次给我第一个-我不希望这样。好的。我更改了我的答案,所以电话将为空。使用
COALESCE
,它仍然显示第一个联系人电子邮件地址,如果第二个是
null
,这就是您在问题中的示例的工作原理。你可以随意摆脱它。我需要变得有活力——所以这似乎是有道理的。还需要消化。我喜欢您的许多答案(有相当一部分)都使用同一个工具的方式-强制转换为XML,交叉应用节点。@Eli如您所知,SQL Server在设计上是声明性的。当然,您可以使用经典的动态SQL(这可能更有效),但我喜欢XML方法的一点是它没有范围问题,XML/源可以是表、视图,甚至是带有派生列的自定义查询。例如,我有一个表值函数,它可以将几乎任何select转换为EAV结构。作为一个TVF,它可以被合并到交叉应用程序中,也可以被另一个查询使用。我试图将您的概念实现到实际数据集中,但是,我遇到了一些问题,“contactnumber”字段返回非数值,他们在转换失败等情况下破坏了查询。我在第二个交叉应用中的“不在”部分添加了我不希望“取消插入”的所有字段,但没有用:(@Eli显然,我们在列名中有一些意外的值/格式。请参阅编辑简化版。也许这将有助于任务/开发这就是我开始的地方…我需要“contact”一词后面的值。我尝试编辑您的“where a.value('local-name(.),'varchar(100)”,而不是('id','person')行)`要使所有字段都不以contact开头,尽管它仍在拾取一些值。。。
Select A.ID
      ,A.Person
      ,C.*
 From  @YourTable A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Item  = replace(a.value('local-name(.)','varchar(100)'),'_x0020_',' ')
                      ,Value = a.value('.','varchar(max)') 
                 From  B.XMLData.nodes('/row')  as C1(n)
                 Cross Apply C1.n.nodes('./@*') as C2(a)
                 Where a.value('local-name(.)','varchar(100)') not in ('id','person')
             ) C