是否有相当于在派生表中放置order by子句的东西?

时间:2012-04-27 15:16:45

标签: sql sybase derived-table

这是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,其中有一个sum(status)= 4或类似的东西。那会找到2个状态2的人。

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

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

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

多汁的,没有?

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分: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

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