2016-07-19 35 views
1

我有像数据的两个表:MSSQL/TSQL分离字段为行上值

表:test_results

ID |test_id |test_type |result_1 |amps  |volts  |power  | 
----+-----------+-----------+-----------+-----------+-----------+-----------+ 
1 |101  |static  |10.1  |5.9  |15   |59.1  | 
2 |101  |dynamic |300.5  |9.1  |10   |40.1  | 
3 |101  |prime  |48.9  |8.2  |14   |49.2  | 
4 |101  |dual  |235.2  |2.9  |11   |25.8  | 
5 |101  |static  |11.9  |4.3  |9   |43.3  | 
6 |101  |prime  |49.9  |5.8  |15   |51.6  | 

表:test_records

ID |model  |test_date |operator | 
----+-----------+-----------+-----------+ 
101 |m-300  |some_date |john doe | 
102 |m-243  |some_date |john doe | 
103 |m-007  |some_date |john doe | 
104 |m-523  |some_date |john doe | 
105 |m-842  |some_date |john doe | 
106 |m-252  |some_date |john doe | 

我正在编写一份如下所示的报告:

           |static           |dynamic          | 
test_id |model  |test_date |operator |result_1 |amps  |volts  |power  |result_1 |amps  |volts  |power  | 
-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+ 
101  |m-300  |some_date |john doe |10.1  |5.9  |15   |59.1  |300.5  |9.1  |10   |40.1  | 

左外连接,像这样:

SELECT 
    A.ID AS test_id, model, test_date, operator, 
    B.result_1, B.amps, B.volts, B.power, 
    C.result_1, C.amps, C.volts, C.power 
FROM 
    test_records A 
LEFT JOIN 
    test_results B 
ON 
    A.ID = B.test_id 
    AND 
    B.test_type = 'static' 
LEFT JOIN 
    test_results C 
ON 
    A.ID = C.test_id 
    AND 
    C.test_type = 'dynamic' 

但我遇到了一个问题。 “静态”和“主要”测试运行两次。 我不知道如何区分他们创建自己的4个领域。 所需报告的抽象(简化)视图看起来像:

|static  |dynamic |prime  |dual  |static2 |prime2  | 
|4 fields |4 fields |4 fields |4 fields |4 fields |4 fields | 

这甚至可能吗? 注:

  1. 我标注4场的组,HTML,所以不用担心标签
  2. 不是每个测试将运行“静态”和“素”的两倍。所以这是一个If(“static”和“prime”)被发现两次的情况,请执行此SQL。
  3. 我想我们会让我们的工程师在第二次测试中附加一个2来消除问题,所以这个问题更多的是出于好奇,知道什么方法可以解决这样的问题。
+0

的“4个领域”是一个抽象。它将从字面上是4个独立字段的sql输出。不需要做任何额外的工作来制作某种逗号分隔的列表。每组4个字段与test_type相关联。查看我的文章中的第三个代码块,查看未抽象的版本。 – Van

+0

'test_results'表中有2条记录'101&static'您想如何显示它们? – NEER

+0

您可以使用'test_sequence'列来区分多次执行相同的'test_type'。 –

回答

0

如果你有另一个领域(这里我使用ID),你知道总是要对该领域进行排序,你可以使用一个窗口函数给他们连续的值,然后加入到那个领域。就像这样:

WITH test_records_numbered AS 
( 
    SELECT test_id, test_type, result_1, amps, volts, power, 
      ROW_NUMBER() OVER (PARTITION BY test_id, test_type ORDER BY ID) as type_num 
    FROM test_records 
) 
SELECT 
    A.ID AS test_id, model, test_date, operator, 
    B.result_1, B.amps, B.volts, B.power, 
    C.result_1, C.amps, C.volts, C.power 
FROM test_records A 
LEFT JOIN test_records_numbered B 
     ON A.ID = B.test_id AND B.test_type = 'static' and B.type_num = 1 
LEFT JOIN test_records_numbered C 
     ON A.ID = C.test_id AND C.test_type = 'dynamic' and C.type_num = 2 

我用一个CTE使其更清晰,但你可以使用子查询,你会(当然)必须有相同的子查询两次在SQL,大多数服务器将有没有我期望的CTE优化没有问题。

我觉得这个解决方案有点“黑客”。你真的想让你的原始数据拥有它所需要的所有信息。所以我认为,让您的应用程序开发人员修改其代码(FWIW)是一件好事。

如果这不得不进入生产,我想我会打出来的编号为视角的喜光的可疑的商业规则的编纂(并可以很容易地改变)

+0

您的示例中有一些小错误,但这是我正在寻找/希望的解决方案。感谢您向我展示CTE解决方案并列出替代方案。错误:在CTE中没有FROM。JOIN使用与CTE不同的名称。 – Van

+0

@van我修复了FROM问题,但它看起来像加入了'test_results_numbered',所以我没有看到第二个错字。 – Hogan

+1

测试\ _ **记录** _编号和测试\ _ **结果** _编号。这些总是让我在调试一个小时后面临的错别字错误lol – Van