微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SQL难题根据给定的值找到正确的答案

如何解决SQL难题根据给定的值找到正确的答案

表T具有以下4列

Column 1    Guesses (Column2)  Correct (Column3) Almost Correct (Column4)
Game1             ABDC                 2                2
Game1             ABCF                 3                0
Game1             BAFD                 1                2
Game2             EFGD                 3                0
Game2             EFHG                 2                2
Game2             EFGI                 3                0

我想编写一个SQL查询来获得以下结果(基于正确且几乎正确的列,它应该找到正确的答案,如下所示)

Game (Column1)    Results (Column2)
Game1              ABCD
Game2              EFGH

注意:结果列需要考虑猜测(不正确),正确列和几乎正确的列,并预测正确的结果,如结果列所示。

解决方法

您似乎希望每场比赛排成一排,并附带正确答案(或也许正确/几乎正确)的最大猜测。

如果是这样,则可以将distinct on用于聚合:

select distinct on (column1) column1,guess,sum(correct + almost_correct)
from t
group by column1,guess
order by column1,sum(correct + almost_correct) desc;
,

a)我看到了,认为这是一个有趣的问题。另一个有趣的问题是,我使用SQL Server,但从未使用过Postgres。因此,我尝试在t-sql中解决此问题,然后将其转换。结果可能是错误的Postgres SQL,但它确实适用于DB_fiddle。

b)正如我知道的那样,我将要对其进行转换并希望使其尽可能简单,因此我寻求一个“可行的”答案,而不是最好的答案。它需要一些捷径(例如,一次只能玩一场游戏,尽管会使用该游戏的所有猜测;也只能使用A到J作为字母)。因此,您的解决方案将需要对此进行改进。

c)逻辑相对简单-这是蛮力方法

  • 获取所有可能的4个字符的字母组合(例如AAAA,AAAB,AAAC等)

  • 进行第一个猜测,并对每个组合进行评估,得出正确的数字和接近正确的数字

  • 排除数字正确和数字关闭与原始值不匹配的所有行

d)我假设数字“几乎正确”是字母不在正确位置但在正确位置旁边的数字(例如,如果答案是ABCD,而您猜ABDE ,那么几乎有一个正确的答案-D在一个点之外)。如果这不正确,但几乎正确,那么您需要在delete语句中调整WHERE子句。

e)此处可以进行一些重大的效率改进,例如,对于首次运行,仅插入与首次猜测的结果相匹配的可能性。但这更容易阅读。

DO $$

DECLARE CurrentGuessNum integer;
DECLARE CurrentGuess varchar(4);
DECLARE CurrentNumCorrect integer;
DECLARE CurrentNumClose integer;
DECLARE Guess1 varchar(1);
DECLARE Guess2 varchar(1);
DECLARE Guess3 varchar(1);
DECLARE Guess4 varchar(1);

BEGIN

CREATE TEMPORARY TABLE PuzzleGuesses (GuessNum integer,Guess varchar(4),NumCorrect integer,NumClose integer);
INSERT INTO PuzzleGuesses (GuessNum,Guess,NumCorrect,NumClose) VALUES
(1,'ABDC',2,2),(2,'ABCF',3,0),(3,'BAFD',1,2);



-- Initial setup for brute force table

CREATE TEMPORARY TABLE GuessPossibilities (GuessChar1 varchar(1),GuessChar2 varchar(1),GuessChar3 varchar(1),GuessChar4 varchar(1));

WITH PossibleChars AS
        (SELECT 'A' AS GuessChar UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D' UNION SELECT 'E' UNION SELECT 'F' UNION SELECT 'G' UNION SELECT 'H' UNION SELECT 'I' UNION SELECT 'J')
    INSERT INTO GuessPossibilities (GuessChar1,GuessChar2,GuessChar3,GuessChar4)
        SELECT  PC1.GuessChar,PC2.GuessChar,PC3.GuessChar,PC4.GuessChar
        FROM    PossibleChars AS PC1
                CROSS JOIN PossibleChars AS PC2
                CROSS JOIN PossibleChars AS PC3
                CROSS JOIN PossibleChars AS PC4;


-- Try each guess. Delete rows that don't get the same result.

CurrentGuessNum := 1;

WHILE EXISTS (SELECT * FROM PuzzleGuesses AS PG WHERE GuessNum = CurrentGuessNum)
    LOOP

    SELECT PG.Guess INTO CurrentGuess FROM PuzzleGuesses AS PG WHERE PG.GuessNum = CurrentGuessNum;
    SELECT PG.NumCorrect INTO CurrentNumCorrect FROM PuzzleGuesses AS PG WHERE PG.GuessNum = CurrentGuessNum;
    SELECT PG.NumClose INTO CurrentNumClose FROM PuzzleGuesses AS PG WHERE PG.GuessNum = CurrentGuessNum;


    -- Get each character from Guess to do single-character comparisons.
    -- Using LEFT(RIGHT()) because not sure how Postgres does SUBSTRING
    SELECT LEFT(CurrentGuess,1)           INTO Guess1;
    SELECT LEFT(RIGHT(CurrentGuess,3),1) INTO Guess2;
    SELECT LEFT(RIGHT(CurrentGuess,1) INTO Guess3;
    SELECT LEFT(RIGHT(CurrentGuess,1),1) INTO Guess4;

    CurrentGuessNum := CurrentGuessNum + 1;


    -- Delete any rows that,when compared with current guess,don't have same result

    DELETE FROM GuessPossibilities AS A
        WHERE   CASE WHEN Guess1 = A.GuessChar1 THEN 1 ELSE 0 END 
                + CASE WHEN Guess2 = A.GuessChar2 THEN 1 ELSE 0 END
                + CASE WHEN Guess3 = A.GuessChar3 THEN 1 ELSE 0 END
                + CASE WHEN Guess4 = A.GuessChar4 THEN 1 ELSE 0 END
                <> CurrentNumCorrect
                OR
                CASE WHEN Guess1 <> A.GuessChar1 AND Guess1 = A.GuessChar2 THEN 1 ELSE 0 END
                + CASE WHEN Guess2 <> A.GuessChar2 AND (Guess2 = A.GuessChar1 OR Guess2 = A.GuessChar3) THEN 1 ELSE 0 END
                + CASE WHEN Guess3 <> A.GuessChar3 AND (Guess3 = A.GuessChar2 OR Guess3 = A.GuessChar4) THEN 1 ELSE 0 END
                + CASE WHEN Guess4 <> A.GuessChar4 AND Guess4 = A.GuessChar3 THEN 1 ELSE 0 END
                <> CurrentNumClose;
    END LOOP;

END $$;

SELECT      CONCAT(GuessChar1,GuessChar4) AS Possible_Correct_Answers
    FROM    GuessPossibilities;

DROP TABLE GuessPossibilities;
DROP TABLE PuzzleGuesses;

以下是Game 1Game 2的DB_fiddles

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。