SQL谜题(根据给定的值找到正确答案)

SQL谜题(根据给定的值找到正确答案),sql,string,postgresql,character,puzzle,Sql,String,Postgresql,Character,Puzzle,表T有以下4列 Column 1 Guesses (Column2) Correct (Column3) Almost Correct (Column4) Game1 ABDC 2 2 Game1 ABCF 3 0 Game1 BAFD 1

表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, 2), 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, GuessChar2, GuessChar3, GuessChar4) AS Possible_Correct_Answers
    FROM    GuessPossibilities;

DROP TABLE GuessPossibilities;
DROP TABLE PuzzleGuesses;

这里是DB_小提琴和

到目前为止你尝试了什么?。分享一些代码是的,结果应该是每场比赛一行。但是,结果需要考虑猜测不正确,并预测正确的结果,如结果列所示。@Datalearner。你的问题中没有错误的猜测。在任何情况下,这应该是非常接近你想要的,你应该能够调整解决方案为您的特定规则-这是没有解释的问题。我编辑了问题,以使其更清楚。是的,猜测是不正确的。基于不正确的猜测和显示有多少字母是正确的正确列,以及显示有多少字母几乎正确的几乎正确列。需要编写Sql查询以显示结果中所示的正确答案。