SQL使用两个表中的值作为其他列名作为列名

问题描述:

我有点难以忍受我需要为工作编写的查询。我有以下两个表格:SQL使用两个表中的值作为其他列名作为列名

|===============Patterns==============| 
|type  | bucket_id | description | 
|-----------------------|-------------| 
|pattern a | 1   | Email  | 
|pattern b | 2   | Phone  | 


|==========Results============| 
|id  | buc_1  | buc_2 | 
|-----------------------------| 
|123 | pass  |   | 
|124 | pass  |fail  | 

在结果表中,我可以看到实体124未通过buc_2中的验证检查。查看模式表,我可以看到bucket 2属于模式b(bucket_id对应于结果表中的列名),所以实体124未通过手机验证。但是,我该如何编写一个查询来将这两个表连接到一列的值?如何调用此查询的限制很可能会阻止我使用任何游标。

+2

你需要什么来得到结果?你不能以这种方式“加入”它们,但是你可以为每个'buc_X'列创建一个特定的连接子句。 – 2014-12-13 00:00:59

+2

你可以重组你的桌子吗?这不是规范化数据库的良好实现。每当你添加一个新的模式,你需要添加一个新的列到你的结果表... – sgeddes 2014-12-13 00:09:46

+0

哪个版本的Oracle DB你有?你应该看看PIVOT和UNPIVOT的概念 - http://oracle-base.com/articles/11g/pivot-and-unpivot-operators-11gr1.php – Steam 2014-12-13 00:26:33

如果您使用Oracle≥11g,另一种方法是使用UNPIVOT operation。这将在查询执行转换成排列:

select * from Results 
unpivot ("result" for "bucket_id" in ("buc_1" as 1, "buc_2" as 2)) 
join Patterns 
using("bucket_id") 
where "result" = 'fail'; 

不幸的是,你还是要硬编码的列名称。

请参阅http://sqlfiddle.com/#!4/a3eae/17

+0

Steam上面提到了pivot/unpivot,但我很高兴看到一个语法的例子!漂亮的功能!我能够使用它来到我需要的地方。谢谢! – Moose 2014-12-15 15:04:59

一些粗俗的解决方案:

SELECT "id", "description" FROM 
Results JOIN Patterns 
ON "buc_1" = 'fail' AND "bucket_id" = 1 

union all 

SELECT "id", "description" FROM 
Results JOIN Patterns 
ON "buc_2" = 'fail' AND "bucket_id" = 2 

或者,一个非常可能是更好的执行计划:

SELECT "id", "description" FROM 
Results JOIN Patterns 
ON "buc_1" = 'fail' AND "bucket_id" = 1 
OR "buc_2" = 'fail' AND "bucket_id" = 2; 

这将为每个id斗1有失败病例报告所有故障描述或2.

请参阅http://sqlfiddle.com/#!4/a3eae/8为一个现场示例


话虽这么说,在的解决办法是可能是您的模式更改为更易于管理。假设使用association table来存储每个失败的测试 - 因为您事实上在这里有一个many to many relationship

+0

我希望改变模式是一种选择!当我看到桌子时,我有点生气。这个联盟的想法很聪明!我可以使用它,但我必须看看执行时间如何。尽管我一次只能拉一个id,但结果表中会有数百万个值。 – Moose 2014-12-13 01:42:51

在我看来,你真正想知道的是在条件失败的情况下,Pattern条目的描述(在您的示例Phone中)。不管具体的例子是什么,你都想要一个满足这种条件的解决方案,而不仅仅是你的特定例子。

我同意上面的评论。您的存储区条目应该是元组(行)而不是参数,并且您应该共享每个表上的ID,以便实际加入它们。例如,考虑添加一个存储桶列并为其编号索引,然后添加一个结果列来存储状态。就像这样:

|===============Patterns==============| 
    |type  | bucket_id | description | 
    |-----------------------|-------------| 
    |pattern a | 1   | Email  | 
    |pattern b | 2   | Phone  | 


    |==========Results====================| 
    |entity_id  | bucket_id |status | 
    |-------------------------------------| 
    |123   | 1   |pass | 
    |124   | 1   |pass | 
    |123   | 2   |  | 
    |124   | 2   |fail | 

1,使用一个内连接:http://www.w3schools.com/sql/sql_join_inner.asp和WHERE子句来筛选只有那些失败的水桶:

2,请问这个例子帮助?

SELECT Patterns.type, Patterns.description, Results.entity_id,Results.status 
INNER JOIN Results 
ON 
Patterns.bucket_id=Results.bucket_id 
WHERE 
Results.status=fail 

最后,我还要一个primary_key列添加到每个表,以确保索引是每一个独特的组合更快。

谢谢!