有条件加入MS SQL

问题描述:

我有一个DB表来存储基本的历史。我试图保持它超级通用。有条件加入MS SQL

表看起来像:

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 

我想是这样的,它适用于“状态从”,但不是“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字段中的日期

+0

因为你正在做的左联接你的条件也不会留下任何记录,但只会让他们空。这是你想要的吗? – GuidoG

+0

是的。我需要带回所有的历史,但有一个statusTypeID字段,然后我想加入状态表来获取文本名称。 – Darren

+0

对不起,但我没看到预期的结果。 –

Joinin g不支持动态表格。

你已经通过tsql-stored-procedure和一些cursour-logic并且手动建立你的结果集。或者,如果您只有可能的表格,请加入每个人并设置仅评估为真的条件,如果您想“加入”每个表格。

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语句中的某种子查询可能更好也更易于阅读。

+0

请参考您的'或'声明 - 这正是我在我的例子中试图做的。我添加了一个更新,显示我的新代码,我得到了相同的错误 – Darren

我和我最初的脚本非常接近。从这个答案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 
+0

如果解决您的问题,将其标记为已接受,所以其他现在已经解决。 –

+0

谢谢,虽然我必须等待2天来标记我自己的答案。 – Darren