需要SQL查询帮助 - 第一个表中的多个行应该匹配第二个表

时间:2017-04-06 02:34:31

标签: sql join group-by sql-server-2014

Problem Illustration 我试图找到神奇的查询来生成摘要信息。我已将我的问题映射到虚构的插图中。我有' WaterLeakage%'记录在酒店房间发生泄漏数年的表格。

我有另一张表,以每升表的数字记录WaterConsumption。

现在我必须在给定的日期范围内找到给定房间号的实际漏水量。

基本上我必须在WaterLeakage%'中排除几行。表格中的几行“WaterConsumption”'表。我试图找出神奇有效的查询来找到这个。无法找到它,请帮助。

2 个答案:

答案 0 :(得分: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 ROOM_NUMBER=@ROOM_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;

我现在非常接近解决方案。基本上我改变了我的想法。我现在将加入反向。

答案 1 :(得分: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 ROOM_NUMBER=@ROOM_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 ROOM_NUMBER=@ROOM_NUMBER AND START_DATE = @START_DATE AND END_DATE=@END_DATE AND WATER_LEAKAGE_PERCENT=@WATER_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