条件加入MS SQL

时间:2016-09-16 14:15:15

标签: sql-server

我有一个DB表来存储基本历史。我试图让它保持超级通用性。

表格如下:

HistoryID   Action      Table       PrimaryKey  Field           OldValue    NewValue            User                DateTime
--------------------------------------------------------------------------------------------------------------------------------------------
240233      Added       QueueItem   17177       QueueItemID     17177                           XXXXXXXXXXXXXXX 2016-09-16 08:38:58.060
240237      Modified    QueueItem   17177       StatusTypeID    1           2                   XXXXXXXXXXXXXXX 2016-09-16 08:38:59.163
240240      Modified    QueueItem   17177       StatusTypeID    2           3                   XXXXXXXXXXXXXXX 2016-09-16 08:39:00.850
240241      Modified    QueueItem   17177       PackageID       0                               XXXXXXXXXXXXXXX 2016-09-16 08:39:00.850
240249      Modified    QueueItem   17177       StatusTypeID    3           4                   XXXXXXXXXXXXXXX 2016-09-16 08:39:09.207
240256      Modified    QueueItem   17177       StatusTypeID    4           5                   XXXXXXXXXXXXXXX 2016-09-16 08:39:10.163
240257      Modified    QueueItem   17177       OutputDateTime              9/16/2016 8:39:10   XXXXXXXXXXXXXXX 2016-09-16 08:39:10.163

我想知道的是,有条件地加入取决于Field的值。我想我不得不使用t-SQL,虽然我有点卡住了。

我可以在场上的位置进行个人选择,然后结合我的所有结果,但是不确定是否有更好的方法?

伪代码将类似于:

select h.*, s.[name] from history h 
    some kind of condition that when satified joins the statusType table and if not, then perhaps sets s.[name] to null 

我尝试了类似这样的东西,它适用于“StatusFrom”#39;但没有与StatusTo' - 失败,因为它无法将最后一行中的日期转换为int。

select h.*, 
       so.[Name] as StatusFrom, 
       sn.[Name] as StatusTo 
from history h
left outer join StatusType so 
             on so.StatusTypeID = Convert(int, h.OldValue) 
            AND 1 = case WHEN h.field = 'StatusTypeID' 
                         THEN 1
                         else 0
                    end
left outer join StatusType sn
             on sn.StatusTypeID = Convert(int, h.NewValue) 
            AND 1 = case WHEN h.field = 'StatusTypeID' 
                         THEN 1
                         else 0 
                    end
where primarykey = 17177

我会提供更多代码示例,虽然我只是超级卡住了。

我想如果条件满足,我真的只想要实际的连接。这是可能的吗?

更新

预期结果将是:

HistoryID   Action      Table       PrimaryKey  Field           OldValue    NewValue            User                DateTime                StatusFrom      StatusTo
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
240233      Added       QueueItem   17177       QueueItemID     17177                           XXXXXXXXXXXXXXX 2016-09-16 08:38:58.060     NULL            NULL
240237      Modified    QueueItem   17177       StatusTypeID    1           2                   XXXXXXXXXXXXXXX 2016-09-16 08:38:59.163     New             Building
240240      Modified    QueueItem   17177       StatusTypeID    2           3                   XXXXXXXXXXXXXXX 2016-09-16 08:39:00.850     Building        Ready
240241      Modified    QueueItem   17177       PackageID       0                               XXXXXXXXXXXXXXX 2016-09-16 08:39:00.850     NULL            NULL
240249      Modified    QueueItem   17177       StatusTypeID    3           4                   XXXXXXXXXXXXXXX 2016-09-16 08:39:09.207     Ready           Processing
240256      Modified    QueueItem   17177       StatusTypeID    4           5                   XXXXXXXXXXXXXXX 2016-09-16 08:39:10.163     Processing      Done
240257      Modified    QueueItem   17177       OutputDateTime              9/16/2016 8:39:10   XXXXXXXXXXXXXXX 2016-09-16 08:39:10.163     NULL            NULL

根据SWE的回答,我也试过了:

select h.*, so.[Name] as StatusFrom, sn.[Name] as StatusTo from history h
    left outer JOIN StatusType so on so.StatusTypeID = Convert(int, h.NewValue)  and h.field = 'statustypeid'
    left outer JOIN StatusType sn on sn.StatusTypeID = Convert(int, h.NewValue)  and h.field = 'statustypeid'
 where primarykey = 17177

我遇到同样的问题 - 当它遇到newValue字段中的日期时会崩溃

2 个答案:

答案 0 :(得分:0)

不支持加入动态表。

你已经完成了一些带有一些cursour-logic的tsql-stored-procedure并手工构建你的结果集。

或者,如果您只有一些可能的表,请加入所有人并设置仅评估为true的条件,如果您想“加入”每个表。

SELECT * 
FROM a
LEFT JOIN b on a.id = b.id AND a.table = 'b' and a.field = 'id'
LEFT JOIN b on a.id = b.something AND a.table = 'b' and a.field = 'something'
LEFT JOIN c...

如果你只想要一个子表的一个值,也许SELECT语句中的某种子选择更好更容易阅读。

答案 1 :(得分:0)

我的初始剧本非常接近。

这个答案的帮助Can I use CASE statement in a JOIN condition?让我想出了这个,这给了我预期的结果:

select h.*, so.[Name] as StatusFrom, sn.[Name] as statusto from history h
    left outer join StatusType so 
        on 
        case
        when h.field='StatusTypeID' and so.StatusTypeID = Convert(int, h.OldValue)  then 1  
        else 0
        end = 1
    left outer join StatusType sn
        on case
        when h.field='StatusTypeID' and sn.StatusTypeID = Convert(int, h.NewValue)  then 1  
        else 0
        end = 1
 where primarykey = 17177