SQL:如何在带有封闭式case语句的查询中添加GROUP BY / ORDER BY子句

时间:2020-01-21 21:13:09

标签: sql group-by subquery sql-order-by case

SELECT DISTINCT *
FROM 
    (SELECT dbtables.[name] as 'back_end_name', 
            CASE
                WHEN dbtables.[name] LIKE '_Result%' AND CAST(RIGHT(dbtables.[name], LEN(dbtables.[name]) - 7) AS int) = CalculationID
                THEN Calculation.Name
                WHEN dbtables.[name] LIKE '_History%' 
                THEN
                    CASE
                        WHEN LEN(dbtables.[name]) = 9 AND CAST(RIGHT(dbtables.[name], 1) AS int) = HistoryID
                        THEN HistoryMap.TableName
                        WHEN LEN(dbtables.[name]) = 10 AND CAST(RIGHT(dbtables.[name], 2) AS int) = HistoryID
                        THEN HistoryMap.TableName
                        WHEN LEN(dbtables.[name]) = 11 AND CAST(RIGHT(dbtables.[name], 3) AS int) = HistoryID
                        THEN HistoryMap.TableName
                        ELSE 'N/A'
                    END 
                ELSE 'N/A'
            END AS front_end_name,
            indexstats.avg_fragmentation_in_percent,
            indexstats.page_count,
            indexstats.record_count
        FROM Calculation, HistoryMap, sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, 'Sampled') AS indexstats
        INNER JOIN sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id]
        INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id]
        INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id]
        AND indexstats.index_id = dbindexes.index_id
        WHERE indexstats.database_id = DB_ID() AND indexstats.avg_fragmentation_in_percent >= 30) tmp
WHERE front_end_name NOT LIKE '%N/A%'

我有以下查询有效,但是当我只需要1个实例时,“ front_end_name”中的某些数据重复,因此我在最后添加了“ GROUP BY front_end_name”,但它返回错误“ Column'tmp.back_end_name” '在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中”。为什么现在要谈论back_end_name?

当我在第一个WHERE子句之后添加GROUP BY时,在所附查询的末尾,它说front_end_name是无效的列名。

此外,我想订购indexstats.avg_fragmentation_in_percent。显然,我不能在查询的最后执行此操作,因为indexstats对于包含在封闭查询中是本地的。当我尝试在所附查询的末尾执行此操作时,它告诉我“除非已指定TOP,OFFSET或FOR XML,否则ORDER BY子句在视图,内联函数,派生表,子查询和公用表表达式中无效。 。”

关于如何将GROUP BY front_end_name和ORDER BY indexstats.avg_fragmentation_in_percent添加到现有查询的任何提示?对于SQL还是很新的,所以我正在学习。我正在努力避免多次编写案例声明。

谢谢!

1 个答案:

答案 0 :(得分:0)

不要简单地在任何地方添加GROUP BY来删除重复项。这主要用于聚合目的。退后一步,考虑一下您的需求。

  • 首先,问问自己:当 front_end_name 重复时,其他列(back_end_nameavg_fragmentation_in_percent,{{1} },page_count)重复吗?由于您的外部查询使用record_count,因此它们可能不会重复。

  • 现在,考虑一下您的数据。如何为每个重复的DISTINCT处理非重复列?可能是由于联接表front_end_nameCalculationHistoryMap等的粒度所致,根据您计算出的<,表可以具有一对多或多对多关系strong> front_end_name

使用CTE保存原始的 基本 结果,请考虑汇总其他列以避免重复的名称

sys.tables

或者,如果您知道重复的原因,则汇总WITH base AS ( SELECT dbtables.[name] AS back_end_name, CASE WHEN dbtables.[name] LIKE '_Result%' AND CAST(RIGHT(dbtables.[name], LEN(dbtables.[name]) - 7) AS int) = CalculationID THEN Calculation.Name WHEN dbtables.[name] LIKE '_History%' THEN CASE WHEN LEN(dbtables.[name]) = 9 AND CAST(RIGHT(dbtables.[name], 1) AS int) = HistoryID THEN HistoryMap.TableName WHEN LEN(dbtables.[name]) = 10 AND CAST(RIGHT(dbtables.[name], 2) AS int) = HistoryID THEN HistoryMap.TableName WHEN LEN(dbtables.[name]) = 11 AND CAST(RIGHT(dbtables.[name], 3) AS int) = HistoryID THEN HistoryMap.TableName ELSE 'N/A' END ELSE 'N/A' END AS front_end_name, indexstats.avg_fragmentation_in_percent, indexstats.page_count, indexstats.record_count FROM Calculation, HistoryMap, sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, 'Sampled') AS indexstats INNER JOIN sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id] INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id] INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id] AND indexstats.index_id = dbindexes.index_id WHERE indexstats.database_id = DB_ID() AND indexstats.avg_fragmentation_in_percent >= 30 ) SELECT back_end_name, front_end_name, AVG(avg_fragmentation_in_percent) AS avg_page_count, -- ADJUST AGG FUNCTION TO NEEDS SUM(page_count) AS sum_page_count, -- ADJUST AGG FUNCTION TO NEEDS SUM(record_count) AS sum_record_count -- ADJUST AGG FUNCTION TO NEEDS FROM base GROUP BY back_end_name, -- GROUP BY REQUIRES ALL NON-AGG COLUMNS PRESENT IN CLAUSE front_end_name ORDER BY AVG(avg_fragmentation_in_percent)

front_end_name
相关问题