【问题标题】:Order By not working with Top MS SQL QueryOrder By 不使用顶级 MS SQL 查询
【发布时间】:2017-12-05 19:14:19
【问题描述】:

我正在创建一个查询,该查询应该与我正在从 MsSQL 处理的 DataTable 匹配。这是我第一次在 MsSQL 上工作,所以我试图从我的 MySQL 中找出等效的 MsSQL 查询。

我做了一个自定义查询,它将处理 MySQL 中的 LIMIT 函数到 MsSQL(希望如此)。我在数据表中使用了以下查询:

    SELECT * FROM (
        SELECT top 20 CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) AS week_name, 
        AVG(DATEDIFF(day, CONVERT(date, [UnloadDate]), CONVERT(date, [DeliveryDate]))) as Average_Delivery_Days
        FROM [CARGODB].[dbo].[Cargo_Transactions] 
        WHERE [DeliveryDate] IS NOT NULL AND [DeliveryDate] != 0 
        AND [UnloadDate] IS NOT NULL AND [UnloadDate] != 0 AND [DeliveryDate] > [UnloadDate] AND [Deleted] = 0 and [StageID] = 'D' 
        AND [RouteID] IS NOT NULL AND [RouteID] != '' AND CONVERT(date, [DeliveryDate]) BETWEEN '2016-01-01' AND GETDATE() 
        AND CONVERT(date, [DeliveryDate]) >= DATEADD(week, -24, getdate()) 
        GROUP BY DATEPART(YEAR,[DeliveryDate]), DATEPART(WEEK,[DeliveryDate]) 
        ORDER BY CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) ASC
    ) as foo
    except
    SELECT * FROM (
        SELECT top 10 CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) AS week_name, 
        AVG(DATEDIFF(day, CONVERT(date, [UnloadDate]), CONVERT(date, [DeliveryDate]))) as Average_Delivery_Days
        FROM [CARGODB].[dbo].[Cargo_Transactions] 
        WHERE [DeliveryDate] IS NOT NULL AND [DeliveryDate] != 0 
        AND [UnloadDate] IS NOT NULL AND [UnloadDate] != 0 AND [DeliveryDate] > [UnloadDate] AND [Deleted] = 0 and [StageID] = 'D' 
        AND [RouteID] IS NOT NULL AND [RouteID] != '' AND CONVERT(date, [DeliveryDate]) BETWEEN '2016-01-01' AND GETDATE() 
        AND CONVERT(date, [DeliveryDate]) >= DATEADD(week, -24, getdate()) 
        GROUP BY DATEPART(YEAR,[DeliveryDate]), DATEPART(WEEK,[DeliveryDate]) 
        ORDER BY CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) ASC
    ) as bar

结果是:

week_name     | Average_Delivery_Days
==================================
2017 Week 36  | 15
2017 Week 39  | 11
2017 Week 41  | 13
2017 Week 42  | 10
2017 Week 38  | 12
2017 Week 40  | 12
2017 Week 35  | 14
2017 Week 43  | 6
2017 Week 37  | 12
2017 Week 44  | 9

但我希望它按周数升序排序,因此它应该显示 36、37、38、39 等等。

我的查询中可能缺少什么?

感谢您的帮助。谢谢!

【问题讨论】:

    标签: mysql sql-server sorting datatable


    【解决方案1】:

    您的 ORDER BY 子句仅影响 TOP 选择;它不对结果集进行排序。在查询末尾添加 ORDER BY 应该可以解决问题。

    不过,我确实看到了另一个问题,那就是您将要对一个包含数字的 VARCHAR 列进行排序。 VARCHAR 按字母顺序排序,因此第 2 周将出现在第 19 周之后。所以我会这样做:

    SELECT 
    /* Explicitly select these columns */
    week_name
    , Average_Delivery_Days
    
    
    FROM (
        SELECT top 20
        /* Add separate columns for numerical year and week */
         iyear = YEAR(DeliveryDate)
        , iweek = DATEPART(WEEK,DeliveryDate)
        , CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) AS week_name, 
        AVG(DATEDIFF(day, CONVERT(date, [UnloadDate]), CONVERT(date, [DeliveryDate]))) as Average_Delivery_Days
        FROM [CARGODB].[dbo].[Cargo_Transactions] 
        WHERE [DeliveryDate] IS NOT NULL AND [DeliveryDate] != 0 
        AND [UnloadDate] IS NOT NULL AND [UnloadDate] != 0 AND [DeliveryDate] > [UnloadDate] AND [Deleted] = 0 and [StageID] = 'D' 
        AND [RouteID] IS NOT NULL AND [RouteID] != '' AND CONVERT(date, [DeliveryDate]) BETWEEN '2016-01-01' AND GETDATE() 
        AND CONVERT(date, [DeliveryDate]) >= DATEADD(week, -24, getdate()) 
        GROUP BY DATEPART(YEAR,[DeliveryDate]), DATEPART(WEEK,[DeliveryDate]) 
        ORDER BY CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) ASC
    ) as foo
    except
    SELECT * FROM (
        SELECT top 10 CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) AS week_name, 
        AVG(DATEDIFF(day, CONVERT(date, [UnloadDate]), CONVERT(date, [DeliveryDate]))) as Average_Delivery_Days
        FROM [CARGODB].[dbo].[Cargo_Transactions] 
        WHERE [DeliveryDate] IS NOT NULL AND [DeliveryDate] != 0 
        AND [UnloadDate] IS NOT NULL AND [UnloadDate] != 0 AND [DeliveryDate] > [UnloadDate] AND [Deleted] = 0 and [StageID] = 'D' 
        AND [RouteID] IS NOT NULL AND [RouteID] != '' AND CONVERT(date, [DeliveryDate]) BETWEEN '2016-01-01' AND GETDATE() 
        AND CONVERT(date, [DeliveryDate]) >= DATEADD(week, -24, getdate()) 
        GROUP BY DATEPART(YEAR,[DeliveryDate]), DATEPART(WEEK,[DeliveryDate]) 
        ORDER BY CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) ASC
    ) as bar
     /* sort by the numeric columns */
     ORDER BY foo.iyear, foo.iweek
    

    【讨论】:

    • 嗨戴夫!感谢您的回答。但是,我收到了这个错误:Msg 104, Level 16, State 1, Line 35 ORDER BY items must appear in the select list if the statement contains a UNION, INTERSECT or EXCEPT operator. Msg 104, Level 16, State 1, Line 35 ORDER BY items must appear in the select list if the statement contains a UNION, INTERSECT or EXCEPT operator.
    【解决方案2】:

    对于任何有类似情况的人,我终于得到了正确的查询:

    SELECT 
    /* Explicitly select these columns */
    week_name, Average_Delivery_Days, delivery_date_year, delivery_date_week
    FROM (
    SELECT top 20
    CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) AS week_name, 
    DATEPART(YEAR,[DeliveryDate]) as delivery_date_year, DATEPART(WEEK,[DeliveryDate]) as delivery_date_week,
    AVG(DATEDIFF(day, CONVERT(date, [UnloadDate]), CONVERT(date, [DeliveryDate]))) as Average_Delivery_Days
    FROM [CARGODB].[dbo].[Cargo_Transactions] 
    WHERE [DeliveryDate] IS NOT NULL AND [DeliveryDate] != 0 
    AND [UnloadDate] IS NOT NULL AND [UnloadDate] != 0 AND [DeliveryDate] > [UnloadDate] AND [Deleted] = 0 and [StageID] = 'D' 
    AND [RouteID] IS NOT NULL AND [RouteID] != '' AND CONVERT(date, [DeliveryDate]) BETWEEN '2016-01-01' AND GETDATE() 
    AND CONVERT(date, [DeliveryDate]) >= DATEADD(week, -24, getdate()) 
    GROUP BY DATEPART(YEAR,[DeliveryDate]), DATEPART(WEEK,[DeliveryDate]) 
    ORDER BY delivery_date_year ASC, delivery_date_week ASC
    ) as foo
    EXCEPT
    SELECT week_name, Average_Delivery_Days, delivery_date_year, delivery_date_week
    FROM (
    SELECT top 10
    CAST(DATEPART(YEAR,[DeliveryDate]) as varchar) + ' Week ' + CAST(DATEPART(WEEK,[DeliveryDate]) AS varchar) AS week_name, 
    DATEPART(YEAR,[DeliveryDate]) as delivery_date_year, DATEPART(WEEK,[DeliveryDate]) as delivery_date_week,
    AVG(DATEDIFF(day, CONVERT(date, [UnloadDate]), CONVERT(date, [DeliveryDate]))) as Average_Delivery_Days
    FROM [CARGODB].[dbo].[Cargo_Transactions] 
    WHERE [DeliveryDate] IS NOT NULL AND [DeliveryDate] != 0 
    AND [UnloadDate] IS NOT NULL AND [UnloadDate] != 0 AND [DeliveryDate] > [UnloadDate] AND [Deleted] = 0 and [StageID] = 'D' 
    AND [RouteID] IS NOT NULL AND [RouteID] != '' AND CONVERT(date, [DeliveryDate]) BETWEEN '2016-01-01' AND GETDATE() 
    AND CONVERT(date, [DeliveryDate]) >= DATEADD(week, -24, getdate()) 
    GROUP BY DATEPART(YEAR,[DeliveryDate]), DATEPART(WEEK,[DeliveryDate]) 
    ORDER BY delivery_date_year ASC, delivery_date_week ASC
    ) as bar ORDER BY delivery_date_week, delivery_date_year
    

    【讨论】:

      猜你喜欢
      • 2018-04-02
      • 1970-01-01
      • 2021-11-17
      • 2020-01-05
      • 2011-07-19
      • 2010-09-17
      • 2023-04-02
      • 2019-01-21
      • 1970-01-01
      相关资源
      最近更新 更多