0

这是sybase 15。这是我的问题。

我有 2 张桌子。

t1.jobid          t1.date
------------------------------
1                   1/1/2012
2                   4/1/2012
3                   2/1/2012
4                   3/1/2012

t2.jobid   t2.userid    t2.status
-----------------------------------------------
1              100            1
1              110            1
1              120            2
1              130            1
2              100            1
2              130            2
3              100            1
3              110            1
3              120            1
3              130            1
4              110            2
4              120            2

我想找到他们最近两个工作状态为 2 的所有人。

我的计划是获取连接 t1 和 t2 的派生表的前 2 个,并为给定用户按日期向后排序。因此,前两个将是给定用户的最新信息。

所以这会给我这些人最近的工作号码。不是每个人都从事每项工作。

然后我将进行一个外部查询,该查询与派生表相结合,搜索状态 2 的总和(状态)= 4 或类似的东西。那将找到具有 2 个状态 2 的人。

但是 sybase 不允许我在派生表中使用 order by 子句。

关于如何解决这个问题的任何建议?

我总是可以编写一个小程序来遍历所有用户,但我会尝试用它制作一个 horrendus sql。

多汁的,不是吗?

4

2 回答 2

1
With Table1 As
    (
    Select 1 As jobid, '1/1/2012' As [date]
    Union All Select 2, '4/1/2012'
    Union All Select 3, '2/1/2012'
    Union All Select 4, '3/1/2012'
    )
    , Table2 As
    (
    Select 1 jobid, 100 As userid, 1 as status
    Union All Select 1,110,1
    Union All Select 1,120,2
    Union All Select 1,130,1
    Union All Select 2,100,1
    Union All Select 2,130,2
    Union All Select 3,100,1
    Union All Select 3,110,1
    Union All Select 3,120,1
    Union All Select 3,130,1
    Union All Select 4,110,2
    Union All Select 4,120,2
    )
    , MostRecentJobs As
    (
    Select T1.jobid, T1.date, T2.userid, T2.status
        , Row_Number() Over ( Partition By T2.userid Order By T1.date Desc ) As JobCnt
    From Table1 As T1
        Join Table2 As T2
            On T2.jobid = T1.jobid
    )
Select *
From MostRecentJobs As M2
Where Not Exists    (
                    Select 1
                    From MostRecentJobs As M1
                    Where M1.userid = M2.userid
                        And M1.JobCnt <= 2
                        And M1.status <> 2
                    )
     And M2.JobCnt <= 2

我在这里使用了 Sybase 15 中确实存在的许多功能。首先,我对我的示例数据使用公用表表达式并将我的查询组合在一起。其次,我使用排名功能Row_Number按日期对工作进行排序。

应该注意的是,在您提供的示例数据中,没有用户满足他们最近的两个工作都为“2”状态的要求。

__

编辑

如果您使用的 Sybase 版本不支持排名函数(例如 15.2 之前的 Sybase 15),则需要使用 Counts 模拟排名函数。

Create Table #JobRnks
    (
    jobid int not null
    , userid int not null
    , status int not null
    , [date] datetime not null
    , JobCnt int not null
    , Primary Key ( jobid, userid, [date] )
    )

Insert #JobRnks( jobid, userid, status, [date], JobCnt )    
Select T1.jobid, T1.userid, T1.status, T1.[date], Count(T2.jobid)+ 1 As JobCnt
From    (
        Select T1.jobid, T2.userid, T2.status, T1.[date]
        From @Table2 As T2
            Join @Table1 As T1
                On T1.jobid = T2.jobid
        ) As T1
    Left Join   (
                Select T1.jobid, T2.userid, T2.status, T1.[date]
                From @Table2 As T2
                    Join @Table1 As T1
                        On T1.jobid = T2.jobid
                ) As T2
        On T2.userid = T1.userid
            And T2.[date] < T1.[date]
Group By T1.jobid, T1.userid, T1.status, T1.[date]

Select *
From #JobRnks As J1
Where Not Exists    (
                    Select 1
                    From #JobRnks As J2
                    Where J2.userid = J1.userid
                        And J2.JobCnt <= 2
                        And J2.status <> 2
                    )
    And J1.JobCnt <= 2

在这里使用临时表的原因是为了性能和易于阅读。从技术上讲,您可以将临时表的查询插入用作派生表的两个位置并获得相同的结果。

于 2012-04-27T16:16:28.047 回答
1

您可以通过使用窗口函数添加额外的列来对子查询中的行进行排名。然后选择在其组中具有适当等级的行。

我从未使用过 Sybase,但文档似乎表明这是可能的。

于 2012-04-27T15:20:09.737 回答