2017-09-11 5 views
-2

내 테이블에 아래 형식의 데이터가 있다고 가정하면 십진법을 가져와야합니다. 따라서 올바른 십진법을 얻기 위해 SQL 서버에서 가장 빠르고 가장 빠른 쿼리는 무엇입니까? . 행 번호를 얻는 가장 빠르고 가장 빠른 방법은 무엇입니까

내가 성능 값 매개 변수 11.22 3 measureid에서 통과한다고 가정 내 스칼라 함수에 두 개의 매개 변수,

  1. PerformanceValue
  2. Measureid이 있다고 가정, 스칼라 함수는 3을 반환해야

    성능 값 매개 변수에 85.54를 전달하고 measureid에 4를 전달하면 10을 반환한다고 가정합니다.

    는 반환 내가 measureid의 성능 값 매개 변수에 54.00 4를 통과한다고 가정 7.2

    Decile Data

+0

게시 한 마지막 사례 - 7.2를 반환해야합니까? 아니면 그냥 7을 읽어야 했습니까? 이미지가 현재 데이터 형식입니까? – Eli

+5

각 열에 원자 값을 저장하고 반복 그룹을 피하기 위해 테이블을 정규화하는 것이 좋습니다. 그런 다음 간단하게 쿼리하고 성능을 향상시키는 것이 더 쉬울 것입니다. –

+0

http://meta.stackoverflow.com/questions/285551/why-may-i-not-upload-images-of-code-on-so-when-asking-a-question/285557 및 허용 된 답변을 읽어보십시오. –

답변

1

당신이 필요로하는 표는 MeasureID 포함, 수의 범위 (예를 들어, from_valuetill_value)와 Decile. 그런 다음 간단한 WHERE 절을 사용하십시오.

select decile 
from mytable 
where measureid = 4 
    and 54.00 between from_value and till_value; 
0

다른 언급이 있습니다. 가장 좋은 방법은 테이블 디자인을 수정하는 것입니다. 물론 우리 모두는 현실 세계에 살고 있으며 그 베이가 항상 가능하지는 않습니다.

다음은 tempdb에서 "semi-perminant"테이블 개념을 사용합니다. 모든 실행과 함께 기본 기반 테이블을 다시 처리하지 않아도 새로운 측정으로 업데이트됩니다. 이렇게하면 전체 테이블 재 설계 & 프로세스 재 디자인보다 짧은 가능한 가장 빠른 실행 시간을 얻을 수 있습니다.

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 
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 
관련 문제