与 UNION 一起使用时,对每个 SQL Server 查询都不起作用的排序

Posted

技术标签:

【中文标题】与 UNION 一起使用时,对每个 SQL Server 查询都不起作用的排序【英文标题】:Sort on each SQL Server query not working when used with UNION 【发布时间】:2012-12-23 03:11:48 【问题描述】:

我必须合并来自 3 个具有不同列的不同表的数据,并且我想要的输出应该基于每个表的不同排序条件。

我在下面使用此查询,但此查询根据菜单位置对整体结果进行排序,如何更改此查询以对单个查询的结果进行排序

SELECT DISTINCT 
     PID, MENU, Handler, PageLangID, ParentID, IssueID, CatID, MenuPosition 
FROM (
   --Pages Table 
   SELECT TOP 50 
       PageId AS PID,SUBSTRING(PageName,0,20) AS MENU,SUBSTRING(PageInternalLinkURL,0,24) AS Handler, PageLangID,PageInheritance AS ParentID, 1 AS IssueID, 1 AS CatID, 
        PageLinkPosition as MenuPosition  FROM pg_Pages  WHERE PageLangID = 1  ORDER BY PageLinkPosition DESC 
UNION 
--Article Category Table
SELECT TOP 20 p.PageID AS PID, SUBSTRING(c.ArticleCategoryName,0,20) AS MENU,SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler, 
c.LangID,p.PageID,1, ArticleCategoryID, 1 AS MenuPosition FROM art_Category c JOIN pg_Pages p 
ON c.PageID = p.PageID  JOIN art_CategoryType ct ON c.Type = ct.CategoryTypeID WHERE c.LangID =1  AND c.Type =1 
ORDER BY c.ArticleCategoryName  
UNION 
--Magazine Table
SELECT TOP 10 p.PageID AS PID, CAST(IssueCode AS varchar(10)),SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler,LangID,p.PageID AS ParentID, m.IssueID AS IssueID, 1, 
       1 AS MenuPosition FROM Magazine m   JOIN pg_pages p ON m.PageID = p.PageID   WHERE LangID =1  ORDER BY 2 DESC  
) AS T  WHERE T.PageLangID = 1 ORDER BY MenuPosition

第二种方式

如果我使用以下查询,则会出现以下错误

消息 156,第 15 级,状态 1,第 4 行 关键字“UNION”附近的语法不正确。 消息 156,第 15 级,状态 1,第 10 行 关键字“UNION”附近的语法不正确。

查询

--Pages Table 
SELECT TOP 50 PageId AS PID,SUBSTRING(PageName,0,20) AS MENU,SUBSTRING(PageInternalLinkURL,0,24) AS Handler, PageLangID,PageInheritance AS ParentID, 1 AS IssueID, 1 AS CatID, 
        PageLinkPosition as MenuPosition  FROM pg_Pages  WHERE PageLangID = 1  ORDER BY PageLinkPosition DESC 
UNION 
--Article Category Table
SELECT TOP 20 p.PageID AS PID, SUBSTRING(c.ArticleCategoryName,0,20) AS MENU,SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler, 
c.LangID,p.PageID,1, ArticleCategoryID, 1 AS MenuPosition FROM art_Category c JOIN pg_Pages p 
ON c.PageID = p.PageID  JOIN art_CategoryType ct ON c.Type = ct.CategoryTypeID WHERE c.LangID =1  AND c.Type =1 
ORDER BY c.ArticleCategoryName  ASC
UNION 
--Magazine Table
SELECT TOP 10 p.PageID AS PID, CAST(IssueCode AS varchar(10)),SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler,LangID,p.PageID AS ParentID, m.IssueID AS IssueID, 1, 
       1 AS MenuPosition FROM Magazine m   JOIN pg_pages p ON m.PageID = p.PageID   WHERE LangID =1  ORDER BY 2 DESC  

样本数据

PID         MENU                 Handler                  PageLangID  ParentID    IssueID     CatID       MenuPosition
----------- -------------------- ------------------------ ----------- ----------- ----------- ----------- ------------
6           Book Review          Page.aspx                1           6           1           18          1
6           Business             Page.aspx                1           6           1           16          1
6           Culture              Page.aspx                1           6           1           3           1
6           Economy              Page.aspx                1           6           1           2           1
6           Finance              Page.aspx                1           6           1           19          1
6           Infrastructure       Page.aspx                1           6           1           17          1
6           Lifestyle            Page.aspx                1           6           1           20          1
6           Others               Page.aspx                1           6           1           21          1
6           People               Page.aspx                1           6           1           7           1
6           Politics             Page.aspx                1           6           1           1           1
6           Sports               Page.aspx                1           6           1           4           1
12          102                  Page.aspx                1           12          3           1           1
12          103                  Page.aspx                1           12          4           1           1
12          106                  Page.aspx                1           12          1           1           1
12          109                  Page.aspx                1           12          5           1           1
1           Home                 Default.aspx             1           0           1           1           10
11          Video                Videos.aspx              1           10          1           1           10
2           About Us             Page.aspx                1           0           1           1           20
5           Articles             Articles.aspx            1           0           1           1           30
6           Categories           Page.aspx                1           0           1           1           40
12          Archive              Page.aspx                1           0           1           1           50
3           News                 News.aspx                1           0           1           1           60
10          Multimedia           Multimedia.aspx          1           0           1           1           70

我希望第一个查询按 ORDER BY PageLinkPosition DESC 排序

ORDER BY c.ArticleCategoryName ASC排序的第二个查询

第三个查询按ORDER BY IssueCode DESC排序

我尝试了很多方法,但无法正常工作。

感谢这方面的帮助

更新:基于标记解决方案的工作查询并进行小幅改动

SELECT DISTINCT PID, MENU, Handler, PageLangID, ParentID, IssueID, CatID, MenuPosition, block, rNum
FROM    
(   --Pages Table 
    SELECT TOP 50 
        PageId AS PID,SUBSTRING(PageName,0,20) AS MENU,SUBSTRING(PageInternalLinkURL,0,24) AS Handler, PageLangID,PageInheritance AS ParentID, 1 AS IssueID, 1 AS CatID, 
        PageLinkPosition as MenuPosition
        ,Block = 1
        ,rNum = ROW_NUMBER() OVER (ORDER BY PageLinkPosition DESC)  
    FROM pg_Pages  
    WHERE PageLangID = 1  
    UNION ALL   -- Better to UNION ALL and then DISTINCT outside
--Article Category Table
    SELECT TOP 20 
        p.PageID AS PID, SUBSTRING(c.ArticleCategoryName,0,20) AS MENU,SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler, 
        c.LangID,p.PageID,1, ArticleCategoryID, 1 AS MenuPosition
        ,Block = 2 
        ,rNum = ROW_NUMBER() OVER (ORDER BY c.ArticleCategoryName )
    FROM art_Category c 
    JOIN pg_Pages p             ON c.PageID = p.PageID  
    JOIN art_CategoryType ct    ON c.Type = ct.CategoryTypeID 
    WHERE c.LangID =1  AND c.Type =1 
    UNION ALL
--Magazine Table
    SELECT TOP 10 p.PageID AS PID, CAST(IssueCode AS varchar(10)),SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler,LangID,p.PageID AS ParentID, m.IssueID AS IssueID, 1, 
       1 AS MenuPosition
       ,Block = 3 
       ,rNum = ROW_NUMBER() OVER (ORDER BY CAST(IssueCode AS varchar(10))DESC)
    FROM Magazine m   
    JOIN pg_pages p ON m.PageID = p.PageID   
    WHERE LangID =1  
) AS T  WHERE T.PageLangID = 1 
ORDER BY Block, rNum

MARK 稍后将他的解决方案更新为 CTE 版本,请查看他的答案。

【问题讨论】:

【参考方案1】:

这应该有效;

;WITH CTE AS
(
    SELECT TOP 50 
         PageId AS PID
        ,SUBSTRING(PageName,0,20) AS MENU
        ,SUBSTRING(PageInternalLinkURL,0,24) AS Handler
        ,PageLangID
        ,PageInheritance AS ParentID
        ,1 AS IssueID
        ,1 AS CatID
        ,PageLinkPosition as MenuPosition
        ,Block = 1
        ,rNum = ROW_NUMBER() OVER (ORDER BY PageLinkPosition DESC)  
    FROM pg_Pages  
    WHERE PageLangID = 1  
    UNION ALL   
--Article Category Table
    SELECT TOP 20 
         p.PageID AS PID
        ,SUBSTRING(c.ArticleCategoryName,0,20) AS MENU
        ,SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler
        ,c.LangID
        ,p.PageID
        ,1
        ,ArticleCategoryID
        ,1 AS MenuPosition
        ,Block = 2 
        ,rNum = ROW_NUMBER() OVER (ORDER BY c.ArticleCategoryName )
    FROM art_Category c 
    JOIN pg_Pages p             ON c.PageID = p.PageID  
    JOIN art_CategoryType ct    ON c.Type = ct.CategoryTypeID 
    WHERE c.LangID =1  AND c.Type =1 
    UNION ALL
--Magazine Table
    SELECT TOP 10 
         p.PageID AS PID
        ,CAST(IssueCode AS varchar(10))
        ,SUBSTRING(p.PageInternalLinkURL,0,24) AS Handler
        ,LangID
        ,p.PageID AS ParentID
        ,m.IssueID AS IssueID
        ,1
        ,1 AS MenuPosition
        ,Block = 3 
        ,rNum = ROW_NUMBER() OVER (ORDER BY CAST(IssueCode AS varchar(10)))
    FROM Magazine m   
    JOIN pg_pages p ON m.PageID = p.PageID   
    WHERE LangID =1  
)
,Deduplicate AS
(
    SELECT   PID
            ,MENU
            ,Handler
            ,PageLangID
            ,ParentID
            ,IssueID
            ,CatID
            ,MenuPosition 
            ,Block
            ,rNum
            ,Occ = ROW_NUMBER() OVER (PARTITION BY PID, MENU, Handler, PageLangID, ParentID, IssueID, CatID, MenuPosition ORDER BY (SELECT NULL))
    FROM CTE
)
SELECT  PID
       ,MENU
       ,Handler
       ,PageLangID
       ,ParentID
       ,IssueID
       ,CatID
       ,MenuPosition 
FROM Deduplicate
WHERE Occ = 1
ORDER BY Block, rNum

【讨论】:

我收到此错误Msg 145, Level 15, State 1, Line 1 ORDER BY items must appear in the select list if SELECT DISTINCT is specified. 如果我忽略 Order by 子句,那么它会得到结果并且显然不是预期的。查询的最后一部分生成错误ORDER BY Block, rNum 我删除了外部DISTINCT 并使用UNION 而不是UNION ALL。你现在遇到什么错误? 我通过在第一行的 SELECT 部分添加 Block, rNum 使其工作,并通过添加排序类型 ASC 或 DESC 进行小改动以获得所需的结果.. 我仍在测试它.. ++ UPDATE++ `ORDER BY CAST(IssueCode AS varchar(10))DESC 我又做了一个改动,你能试试并告诉我吗?

以上是关于与 UNION 一起使用时,对每个 SQL Server 查询都不起作用的排序的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:如何将 UNION 与两个都有 WHERE 子句的查询一起使用?

将“UNION”与“IF EXISTS”一起使用

如何让多个不同的SQL语句一起执行?

UNION、TOP、ORDER BY联合使用时处理顺序是啥?

SQL 性能 UNION 与 OR

SQL语句中:UNION与UNION ALL的区别