在3个表上使用ORDER BY进行UNION CTE

时间:2017-07-26 19:12:38

标签: sql sql-server tsql

这并不容易解释,但是,我相信有更好的方法可以做我设法做的事情并希望得到一些帮助。

我有3个表(T1T2T3)。我需要从T1T2获取最新信息,然后这些结果会返回t3的结果,或者如果t3为空则返回上一个结果。因此,如果LatestDate中有记录,则t3并不重要。另外,如果t3中没有数据且LatestDatet1t2上的数据相同(很少会发生,但又需要相应计划),我想要结果来自t1

这是我得到的一个示例,请注意,实际查询有更多字段,但概念是相同的。

CREATE TABLE [dbo].[t1](
    [Id] [INT] NOT NULL,
    [LatestDate] [DATETIME] NOT NULL
);
CREATE TABLE [dbo].[t2](
    [Id] [INT] NOT NULL,
    [LatestDate] [DATETIME] NOT NULL
);
CREATE TABLE [dbo].[t3](
    [Id] [INT] NOT NULL,
    [LatestDate] [DATETIME] NOT NULL
);
INSERT t1 (Id, LatestDate) VALUES (1, CAST(N'2000-01-01T00:00:00.000' AS DateTime));
INSERT t1 (Id, LatestDate) VALUES (2, CAST(N'2001-01-01T00:00:00.000' AS DateTime));
INSERT t1 (Id, LatestDate) VALUES (3, CAST(N'2002-01-01T00:00:00.000' AS DateTime));
INSERT t2 (Id, LatestDate) VALUES (1, CAST(N'2001-01-01T00:00:00.000' AS DateTime));
INSERT t2 (Id, LatestDate) VALUES (2, CAST(N'2002-01-01T00:00:00.000' AS DateTime));
INSERT t2 (Id, LatestDate) VALUES (4, CAST(N'2003-01-01T00:00:00.000' AS DateTime));
INSERT t3 (Id, LatestDate) VALUES (1, CAST(N'2001-01-01T00:00:00.000' AS DateTime));
INSERT t3 (Id, LatestDate) VALUES (2, CAST(N'2000-01-01T00:00:00.000' AS DateTime));
INSERT t3 (Id, LatestDate) VALUES (5, CAST(N'2004-01-01T00:00:00.000' AS DateTime));
GO;

WITH CTE AS (
    SELECT TOP 1 * FROM (
        SELECT 2 AS Sort, * FROM t1 WHERE t1.id = @UserId
        UNION
        SELECT 3 AS Sort, * FROM t2 WHERE t2.id = @UserId
    ) AS t
    ORDER BY
        t.LatestDate DESC
)
SELECT TOP 1 * FROM (
    SELECT TOP 1 * FROM CTE
    UNION
    SELECT 1 AS Sort, * FROM t3 WHERE t3.id = @UserId
) AS t
ORDER BY
    t.Sort;

预期结果:

When @UserID = 1: 

    Sort    Source    Id    LatestDate
    1       t3        1     1/1/2001

When @UserID = 2: 

    Sort    Source    Id    LatestDate
    1       t3        2     1/1/2000

When @UserID = 3: 

    Sort    Source    Id    LatestDate
    2       t1        3     1/1/2002

When @UserID = 4: 

    Sort    Source    Id    LatestDate
    3       t2        4     1/1/2003

When @UserID = 5: 

    Sort    Source    Id    LatestDate
    1       t3        5     1/1/2004

谢谢!

2 个答案:

答案 0 :(得分:1)

如果我理解正确你想要的东西:

DECLARE @UserID INT  = 5;

WITH cte AS (
    SELECT 1 AS src, 1 as [tbl], * FROM  t1 WHERE id = @UserId
    UNION ALL SELECT 1, 2, * FROM t2 WHERE id = @UserId
    UNION ALL SELECT 3, 3, * FROM t3 WHERE id = @UserId
), cte2 AS (
    SELECT * , ROW_NUMBER() OVER(ORDER BY src DESC, LatestDate DESC, tbl ASC) AS rn
    FROM cte
)
SELECT Id, LatestDate
FROM cte2
WHERE rn = 1;

<强> RextesterDemo

使用PARTITION BY您可以将过滤@userId移至最终部分:

DECLARE @UserID INT  = 5;

WITH cte AS (
    SELECT 1 AS src, 1 as [tbl], * FROM  t1 
    UNION ALL SELECT 1, 2, * FROM t2 
    UNION ALL SELECT 3, 3, * FROM t3 
), cte2 AS (
    SELECT *
     ,ROW_NUMBER() OVER(PARTITION BY Id ORDER BY src DESC, LatestDate DESC, tbl ASC) AS rn
    FROM cte
)
SELECT Id, LatestDate
FROM cte2
WHERE rn = 1
  AND id = @UserID

<强> Rextester Demo2

答案 1 :(得分:1)

这是怎么回事?

假设您将获取t3结果(如果存在) 或者T1或T2的最大结果,如果没有。

if exists(select * from t3 where ID= @ID)
(
  select ID, Max(LatestDate), TN='T3' 
  from t3 
  where ID= @ID
)
else
(
  select top 1 ID, Max(LatestDate) LD,TN
  from (Select *,TN='t1' from T1
        union all
        Select *, TN='t2' from t2) as a
  where id=@ID
  group by ID,TN
  order by LD desc
)