获取行号的最佳和最快方法是什么

时间:2017-09-11 20:35:11

标签: sql sql-server sql-server-2008-r2

假设我的表格中有以下格式的数据,我必须获取十分位数,那么SQL服务器中获得正确十分位数的最佳和最快的查询是什么。

假设我的标量函数中有两个参数,

  1. PerformanceValue
  2. Measureid
  3. 假设我在性能值参数中传递11.22而在measureid中传递3,标量函数应返回3

    假设我在性能值参数中传递85.54而在measureid中传递4则返回10

    假设我在性能值参数中传递54.00而在measureid中传递4则返回7.2

    Decile Data

3 个答案:

答案 0 :(得分:1)

您需要的表格包含viewDidLoad:,数字范围(例如MeasureIDfrom_value)和till_value。然后使用简单的Decile子句:

WHERE

答案 1 :(得分:0)

正如其他人所说。最好的做法是纠正桌子设计。当然,我们都生活在现实世界中,而且这个海湾并非总是可能。

以下使用"半永久性的概念" tempdb中的表。这将通过新的测量更新,而不必在每次执行时重新处理基础表。这将产生最快的执行时间,而不是全表重新设计&流程重新设计。

 IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData;

CREATE TABLE #TestData (
    Measured INT NOT NULL PRIMARY KEY CLUSTERED,
    Decile_3 VARCHAR(15) NOT NULL,
    Decile_4 VARCHAR(15) NOT NULL,
    Decile_5 VARCHAR(15) NOT NULL,
    Decile_6 VARCHAR(15) NOT NULL,
    Decile_7 VARCHAR(15) NOT NULL,
    Decile_8 VARCHAR(15) NOT NULL,
    Decile_9 VARCHAR(15) NOT NULL,
    Decile_10 VARCHAR(15) NOT NULL
    );
INSERT #TestData (Measured, Decile_3, Decile_4, Decile_5, Decile_6, Decile_7, Decile_8, Decile_9, Decile_10) VALUES
    (1, '54.67 - 35.91', '35.90 - 25.63', '25.62 - 19.34', '19.33 - 14.15', '14.14 -  9.10', ' 9.09 -  3.34', ' 3.33 -  0.01', '0'),
    (2, '53.85 - 64.74', '64.75 - 70.90', '70.91 - 86.68', '89.32 - 92.92', '92.91 - 96.54', '96.55 - 98.67', '96.55 - 98.67', '>= 98.68'),
    (3, '11.22 - 18.57', '18.58 - 24.99', '25.00 - 31.84', '31.85 - 38.92', '38.93 - 47.86', '47.87 - 59.99', '60.00 - 79.01', '>= 79.01'),
    (4, '14.13 - 23.25', '23.26 - 33.02', '33.03 - 43.58', '43.59 - 53.96', '53.97 - 63.60', '63.61 - 74.54', '74.55 - 85.52', '>= 85.53'),
    (5, '12.41 - 22.21', '22.22 - 32.30', '32.31 - 40.86', '40.87 - 47.91', '47.92 - 55.25', '55.26 - 63.06', '63.07 - 73.22', '>= 73.23');

-- SELECT * FROM #TestData td'

--======================================================================
--======================================================================

-- create a semi-perminant unpivot table in temp db that simply adds new measurement as opposed to
-- reporcessing the entire base table with every execution.
IF OBJECT_ID('tempdb.dbo.UnpivotData', 'U') IS NULL 
BEGIN   -- DROP TABLE tempdb.dbo.UnpivotData;
    CREATE TABLE tempdb.dbo.UnpivotData (
        Measured INT NOT NULL,
        dType TINYINT NOT NULL,
        BegRange DECIMAL(9,2) NOT NULL,
        EndRange DECIMAL(9,2) NOT NULL,
        PRIMARY KEY CLUSTERED (Measured, dType) 
        );
END;
INSERT tempdb.dbo.UnpivotData (Measured, dType, BegRange, EndRange)
SELECT 
    td.Measured,
    d.dType,
    r.BegRange,
    r.EndRange
FROM 
    #TestData td
    CROSS APPLY ( VALUES (3, td.Decile_3), (4, td.Decile_4), (5, td.Decile_5), (6, td.Decile_6), 
                            (7, td.Decile_7), (8, td.Decile_8), (9, td.Decile_9), (10, td.Decile_10) 
                            ) d (dType, dValue)
    CROSS APPLY ( VALUES (
                        CASE 
                            WHEN CHARINDEX(' - ', d.dValue) > 0 THEN LEFT(d.dValue, 5)
                            WHEN LEFT(d.dValue, 2) = '>=' THEN RIGHT(d.dValue, 5)
                            WHEN LEFT(d.dValue, 2) = '<=' THEN '0'
                            ELSE d.dValue
                        END,
                        CASE 
                            WHEN CHARINDEX(' - ', d.dValue) > 0 THEN RIGHT(d.dValue, 5)
                            WHEN LEFT(d.dValue, 2) = '>=' THEN '9999999.99'
                            WHEN LEFT(d.dValue, 2) = '<=' THEN RIGHT(d.dValue, 5)
                            ELSE d.dValue
                        END
                        ) ) r (BegRange, EndRange)
WHERE 
    NOT EXISTS (SELECT * FROM tempdb.dbo.UnpivotData ud WHERE td.Measured = ud.Measured);

-----------------------------------------------------------

-- Querieng from the temp table is now quite easy.
DECLARE 
    @Measure INT = 4,
    @PerformanceVal DECIMAL(9,2) = 85.54;

SELECT 
    ud.Measured,
    ud.dType,
    ud.BegRange,
    ud.EndRange
FROM 
    tempdb.dbo.UnpivotData ud
WHERE 
    ud.Measured = @Measure
    AND @PerformanceVal BETWEEN ud.BegRange AND ud.EndRange;

结果......

Measured    dType BegRange                                EndRange
----------- ----- --------------------------------------- ---------------------------------------
4           10    85.53                                   9999999.99

答案 2 :(得分:0)

这里的另一个选项可能会更快,因为它开始在Measurid上执行索引搜索,因此只需要解析一行数据......

DECLARE
    @Measureid INT = 4729,
    @Value DECIMAL(9,2) = 85.0;

IF OBJECT_ID('tempdb..#UnpivotData', 'U') IS NOT NULL 
DROP TABLE #UnpivotData;

SELECT 
    td.Measureid,
    d.dType,
    BegRange = ISNULL(CAST(r.BegRange AS DECIMAL(9,2)), 0),
    EndRange = ISNULL(CAST(r.EndRange AS DECIMAL(9,2)), 0)
    INTO #UnpivotData
FROM 
    #TestData td
    CROSS APPLY ( VALUES (3, td.Decile_3), (4, td.Decile_4), (5, td.Decile_5), (6, td.Decile_6), 
                            (7, td.Decile_7), (8, td.Decile_8), (9, td.Decile_9), (10, td.Decile_10) 
                            ) d (dType, dValue)
    CROSS APPLY ( VALUES (
                        CASE 
                            WHEN CHARINDEX(' - ', d.dValue) > 0 THEN LEFT(d.dValue, 5)
                            WHEN LEFT(d.dValue, 2) = '>=' THEN RIGHT(d.dValue, 5)
                            WHEN LEFT(d.dValue, 2) = '<=' THEN '0'
                            ELSE d.dValue
                        END,
                        CASE 
                            WHEN CHARINDEX(' - ', d.dValue) > 0 THEN RIGHT(d.dValue, 5)
                            WHEN LEFT(d.dValue, 2) = '>=' THEN '9999999.99'
                            WHEN LEFT(d.dValue, 2) = '<=' THEN RIGHT(d.dValue, 5)
                            ELSE d.dValue
                        END
                        ) ) r (BegRange, EndRange)
WHERE 
    td.Measureid = @Measureid;

------------------------------------------------------

SELECT 
    ud.Measureid,
    ud.dType,
    ud.BegRange,
    ud.EndRange
FROM 
    #UnpivotData ud
WHERE 
    @Value BETWEEN ud.BegRange AND ud.EndRange;
GO