2017-04-06 3 views
0

Problem Illustration 요약 정보를 생성하는 마법 쿼리를 찾으려고합니다. 내 문제를 가상의 그림으로 매핑했습니다. 나는 몇 년 동안 호텔 방에서 누수가 기록 된 'WaterLeakage %'테이블을 가지고 있습니다.SQL 쿼리 도움말 - 첫 번째 테이블의 여러 행이 두 번째 테이블의 여러 테이블과 일치해야합니다.

각 테이블에 대해 WaterConsumption을 리터 단위로 기록하는 다른 테이블이 있습니다.

이제 지정된 기간 동안 주어진 방의 실제 누수를 리터 단위로 찾아야합니다.

기본적으로 'WaterLockage %'테이블의 여러 행을 'WaterConsumption'테이블의 여러 행으로 그룹화해야합니다. 나는 이것을 찾기 위해 마법 같은 효율적인 쿼리를 찾아 내려고 노력하고있다. 그것을 찾을 수 없습니다, 제발 도와주세요.

답변

0
BEGIN 
    --Input Parameters for calculating water wastage between date range 
    DECLARE @START_DATE_PARAM DATE = '01/10/2017'; 
    DECLARE @END_DATE_PARAM DATE = '01/31/2017'; 

    --Table for daily daily water consumption per room 
    CREATE TABLE #WATER_CONSUMPTION(
    ROOM_NUMBER INT, 
    UDAY DATE, 
    WATER_CONSUMPTION_LITER INT 
    ) 

    --Table for water leakage percent per room for date range 
    CREATE TABLE #WATER_LEAKAGE_PER 
    (
    ROOM_NUMBER INT, 
    START_DATE DATE, 
    END_DATE DATE, 
    WATER_LEAKAGE_PERCENT INT, 
    LEAKAGE_PER_DAY_IN_LITER INT 
    ) 

    -- Leakage in liter per room for each day, This will have multiple entries for room and date if room number and date is available in multiple date ranges, ex. in #WATER_CONSUMPTION table for room number 101 we have multiple entries with overlapping dates 
    CREATE TABLE #DAY_WISE_LEAKAGE 
    (
    ROOM_NUMBER INT, 
    LDATE DATE, 
    LEAKAGE_IN_LITER INT 
    ) 


    -- Raw Data 
    INSERT INTO #WATER_LEAKAGE_PER(ROOM_NUMBER,START_DATE,END_DATE,WATER_LEAKAGE_PERCENT) 
    VALUES(101,'2017/01/15','2017/01/18',30), 
    (102,'2017/01/15','2017/01/18',10), 
    (101,'2017/01/15','2017/02/13',5); 

    -- Raw Data 
    INSERT INTO #WATER_CONSUMPTION 
    VALUES(101,'01/01/2017',1001), 
    (101,'01/02/2017',1001), 
    (101,'01/03/2017',1001), 
    (101,'01/04/2017',1001), 
    (101,'01/05/2017',1001), 
    (101,'01/06/2017',1001), 
    (101,'01/07/2017',1001), 
    (101,'01/08/2017',1001), 
    (101,'01/09/2017',1001), 
    (101,'01/10/2017',1001), 
    (101,'01/11/2017',1001), 
    (101,'01/12/2017',1001), 
    (101,'01/13/2017',1001), 
    (101,'01/14/2017',1001), 
    (101,'01/15/2017',1001), 
    (101,'01/16/2017',1001), 
    (101,'01/17/2017',1001), 
    (101,'01/18/2017',1001), 
    (101,'01/19/2017',1001), 
    (101,'01/20/2017',1001), 
    (101,'01/21/2017',1001), 
    (101,'01/22/2017',1001), 
    (101,'01/23/2017',1001), 
    (101,'01/24/2017',1001), 
    (101,'01/25/2017',1001), 
    (101,'01/26/2017',1001), 
    (101,'01/27/2017',1001), 
    (101,'01/28/2017',1001), 
    (101,'01/29/2017',1001), 
    (101,'01/30/2017',1001), 
    (101,'01/31/2017',1001); 



    DECLARE @ROOM_NUMBER INT 
    DECLARE @START_DATE DATE 
    DECLARE @END_DATE DATE 
    DECLARE @WATER_LEAKAGE_PERCENT INT 

    -- cursor for calculating water wastage pre date range per day available in #WATER_LEAKAGE_PER table 
    DECLARE WATER_LEAKAGE_PER_CURSOR CURSOR FOR 
    SELECT ROOM_NUMBER,START_DATE,END_DATE,WATER_LEAKAGE_PERCENT FROM #WATER_LEAKAGE_PER 

    OPEN WATER_LEAKAGE_PER_CURSOR 

    FETCH NEXT FROM WATER_LEAKAGE_PER_CURSOR 
    INTO @ROOM_NUMBER, @START_DATE ,@END_DATE, @WATER_LEAKAGE_PERCENT 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 
      DECLARE @TOTAL_WATER_USED_FOR_DATE_RANGE INT=0; 
      DECLARE @NUMBER_OF_DAYS INT=0; 
      DECLARE @LEAKAGE_PER_DAY_IN_LITER INT=0; 

      -- Total Liters of water used for 1 date range 
      SELECT @TOTAL_WATER_USED_FOR_DATE_RANGE =SUM(WATER_CONSUMPTION_LITER),@NUMBER_OF_DAYS=COUNT(1) FROM #WATER_CONSUMPTION WHERE [email protected]_NUMBER AND UDAY BETWEEN @START_DATE AND @END_DATE; 

      -- Liters of water leakage per day for selevted date range in cursor 
      SELECT @LEAKAGE_PER_DAY_IN_LITER=((@TOTAL_WATER_USED_FOR_DATE_RANGE*@WATER_LEAKAGE_PERCENT)/100)/@NUMBER_OF_DAYS; 
      UPDATE #WATER_LEAKAGE_PER SET LEAKAGE_PER_DAY_IN_LITER = @LEAKAGE_PER_DAY_IN_LITER WHERE [email protected]_NUMBER AND START_DATE = @START_DATE AND [email protected]_DATE AND [email protected]_LEAKAGE_PERCENT; 

      -- generate dates and water leakage, this will be used for actual calculation of water leakage in date range. 
      ;WITH n AS 
      (
       SELECT TOP (DATEDIFF(DAY, @START_DATE, @END_DATE) + 1) 
       n = ROW_NUMBER() OVER (ORDER BY [object_id]) 
       FROM sys.all_objects 
      ) 
      INSERT INTO #DAY_WISE_LEAKAGE SELECT @ROOM_NUMBER, DATEADD(DAY, n-1, @START_DATE),@LEAKAGE_PER_DAY_IN_LITER 
      FROM n; 

    FETCH NEXT FROM WATER_LEAKAGE_PER_CURSOR 
     INTO @ROOM_NUMBER, @START_DATE ,@END_DATE, @WATER_LEAKAGE_PERCENT 
    END 
    CLOSE WATER_LEAKAGE_PER_CURSOR; 
    DEALLOCATE WATER_LEAKAGE_PER_CURSOR; 

    -- Average of Liters of water leakage per Room number. 
    SELECT ROOM_NUMBER,SUM(LEAKAGE_IN_LITER) FROM #DAY_WISE_LEAKAGE WHERE LDATE BETWEEN @START_DATE_PARAM AND @END_DATE_PARAM GROUP BY ROOM_NUMBER; 

    DROP TABLE #WATER_CONSUMPTION; 
    DROP TABLE #WATER_LEAKAGE_PER; 
    DROP TABLE #DAY_WISE_LEAKAGE 

    END 
+0

대단히 고맙습니다. 커서를 사용하지 않고도이 문제를 해결할 수 있는지 찾아 보려고했습니다. – Datha

+0

커서없이 변환하려고 한 번 더 해보겠습니다. 이미 해결책이 있다면 알려주세요. – Vidyadhar

+0

아니요, 아직은 고민 중입니다. – Datha

1
DECLARE @START_DATE_PARAM DATE = '01/10/2017'; 
DECLARE @END_DATE_PARAM DATE = '01/31/2017'; 
DECLARE @ROOM_NUMBER INT = 101; 

IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '#WATER_CONSUMPTION')) 
    DROP TABLE #WATER_CONSUMPTION; 
IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '#WATER_LEAKAGE_PER')) 
    DROP TABLE #WATER_LEAKAGE_PER; 

--Table for daily daily water consumption per room 
CREATE TABLE #WATER_CONSUMPTION(
ROOM_NUMBER INT, 
UDAY DATE, 
WATER_CONSUMPTION_LITER INT 
) 

--Table for water leakage percent per room for date range 
CREATE TABLE #WATER_LEAKAGE_PER 
(
ROOM_NUMBER INT, 
START_DATE DATE, 
END_DATE DATE, 
WATER_LEAKAGE_PERCENT INT 
) 

-- Raw Data 
INSERT INTO #WATER_LEAKAGE_PER(ROOM_NUMBER,START_DATE,END_DATE,WATER_LEAKAGE_PERCENT) 
VALUES(101,'2017/01/01','2017/01/02',5), 
(102,'2017/01/01','2017/01/05',10), 
(101,'2017/01/04','2017/02/06',10); 

-- Raw Data 
INSERT INTO #WATER_CONSUMPTION 
VALUES(101,'2017/01/01',100), 
(101,'2017/01/02',100), 
(101,'2017/01/03',100), 
(101,'2017/01/04',100), 
(101,'2017/01/05',100), 
(101,'2017/01/06',100), 
(102,'2017/01/01',100), 
(102,'2017/01/02',100), 
(102,'2017/01/03',100), 
(102,'2017/01/04',100), 
(102,'2017/01/05',100); 

DECLARE @TotalLeak REAL = 0; 
SELECT * FROM #WATER_CONSUMPTION; 
SELECT * FROM #WATER_LEAKAGE_PER; 

SELECT * FROM #WATER_CONSUMPTION T1 JOIN (SELECT * FROM #WATER_LEAKAGE_PER WHERE [email protected]_NUMBER) T2 
ON (T1.ROOM_NUMBER=T2.ROOM_NUMBER AND T1.UDAY >= T2.START_DATE AND T1.UDAY <= T2.END_DATE); 

DROP TABLE #WATER_CONSUMPTION; 
DROP TABLE #WATER_LEAKAGE_PER; 

지금은 솔루션에 매우 근접입니다. 기본적으로 나는 생각을 바꿨다. 나는 지금 반대 방향으로 합류 할 것이다.