SQL:选择NOT NULL数据与共享和更改的列?

时间:2014-06-16 17:45:48

标签: sql sql-server

我有一个表(Table1),它具有从多个插入共享的ID:

ID  | RefID | Field_Name | Field_Value | Type
 1  |    1  | NumbAmt    | 1111        | INT
 2  |    1  | LocAdd     | 123 Street  | String
 3  |    1  | LocDesc    | Something   | String
 4  |    1  | LocHidden  | Useless     | Hidden

我无法使用ID,因为它是由插件制作的,RefID是用于将此数据缩小到所有那些 RefID = 1 AND Type!=&#39的主要内容;隐藏'

每当我做一个案例陈述查询时:

SELECT 
  CASE WHEN Field_Name = 'NumbAmt' THEN Field_Value END Amt,
  CASE WHEN Field_Name = 'LocAdd' THEN Field_Value END Address,
  CASE WHEN Field_Name = 'LocDesc' THEN Field_Value END Description
FROM Table1
WHERE RefID = 1
  AND Type IN ('INT','String')

返回结果如:

    Amt     |   Address    | Description
1111        |    NULL      | NULL
NULL        | 123 Street   | NULL
NULL        |    NULL      | Something

我的问题是,我如何收集所有数据,但是如果没有显示所有的NULL,它会分成不同的列? (我的假设让我相信临时表)

或者显示如下:

 Amt     |   Address  | Description
1111     | 123 Street | Something

4 个答案:

答案 0 :(得分:3)

您有几种选择:

  • 将表格加入自身
  • 使用PIVOT
  • 子查询SELECT列表中的所有字段
  • 对每个字段使用OUTER APPLY
  • 使用CTE
  • 考虑重新考虑您的计划!

<强> JOINS

 SELECT
  T1_RefID.RefID, 
  T1_NumbAmt.FieldValue AS NumbAmt,
  T1_LocAdd.FieldValue AS LocAdd
FROM
  (SELECT DISTINCT RefID FROM Table1) T1_RefID
  LEFT JOIN Table1 T1_NumbAmt
    ON T1_RefID.RefID = T1_NumbAmt.RefID AND T1_NumbAmt.FieldName = 'NumbAmt' AND T1_NumbAmt.Type != 'Hidden'
  LEFT JOIN Table1 T1_LocAdd
    ON T1_RefID.RefID = T1_LocAdd.RefID AND T1_LocAdd.FieldName = 'LocAdd' AND T1_LocAdd.Type != 'Hidden'
  /* And so on*/

<强> PIVOT

SELECT
  *
FROM (
  SELECT
    RefID, FieldName, FieldValue
  FROM
    Table1
  WHERE
    Type != 'Hidden'
) AS src
PIVOT (
  MAX(FieldValue)
  FOR FieldName IN (NumbAmt, LocAdd, LocDesc)
) AS PVT

SQL Fiddle

答案 1 :(得分:2)

你当然可以写下这句话:

WITH Record(Field_Value, Field_Name) AS (
  SELECT Field_Value, Field_Name FROM Table1 WHERE RefID = 1
)
SELECT 
  (SELECT Field_Value FROM Record WHERE Field_Name = 'NumbAmt') Amt,
  (SELECT Field_Value FROM Record WHERE Field_Name = 'LocAdd')  Address,
  (SELECT Field_Value FROM Record WHERE Field_Name = 'LocDesc') Description
FROM
  Record

但我强烈建议避免使用entity-attribute-value anti-pattern,并重新设计您的架构。

答案 2 :(得分:2)

您可以为此创建一个视图并使用它

SELECT T.RefID, TAmt.Field_Value as Amt, TAddress.Field_Value as Address, TType.Field_Value as Type FROM
(
    SELECT
        DISTINCT RefID
    FROM
        Table1
    WHERE
        Type IN ('INT', 'String')
) T
LEFT JOIN
    Table1 AS TAmt
ON
    T.RefID = TAmt.RefID
    AND TAmt.Field_Name = 'NumbAmt'
LEFT JOIN
    Table1 AS TAddress
ON
    T.RefID = TAddress.RefID
    AND TAddress.Field_Name = 'LocAdd'
LEFT JOIN
    Table1 AS TType
ON
    T.RefID = TType.RefID
    AND TType.Field_Name = 'LocDesc'

答案 3 :(得分:1)

在关键字段上使用group by,并使用一些聚合函数来提升空值的正确值(我相信max会做,但不能测试我现在坐的位置)

SELECT 
  RefID,
  MAX( CASE WHEN Field_Name = 'NumbAmt' THEN Field_Value ELSE NULL END ) Amt,
  MAX( CASE WHEN Field_Name = 'LocAdd' THEN Field_Value ELSE NULL END ) Address,
  MAX( CASE WHEN Field_Name = 'LocDesc' THEN Field_Value ELSE NULL END ) Description
FROM Table1
GROUP BY RefID