Sql 从一行中获取随机值,同时不同时选择两个存在的值

Sql 从一行中获取随机值,同时不同时选择两个存在的值,sql,postgresql,Sql,Postgresql,我正试图做一些我认为很棘手的事情,但我无法控制它。有点让我发疯。看起来应该比现在容易 所以我有两张桌子。我随机将两个项目显示在一起。当您选择一个项目时,它将作为该项目的投票输入DB,项目ID存储在win_ID列中,另一个项目进入lst_ID列。然后再显示两个随机项,以此类推。现在我的问题是,一旦他们选择了一个项目,我就再也不希望这两个项目对再次显示给那个用户。但是,这些项目可以与其他未被投票反对的项目一起显示。希望这是从那时起。 这就是我正在尝试的问题,但没有成功 SELECT * FROM (

我正试图做一些我认为很棘手的事情,但我无法控制它。有点让我发疯。看起来应该比现在容易

所以我有两张桌子。我随机将两个项目显示在一起。当您选择一个项目时,它将作为该项目的投票输入DB,项目ID存储在win_ID列中,另一个项目进入lst_ID列。然后再显示两个随机项,以此类推。现在我的问题是,一旦他们选择了一个项目,我就再也不希望这两个项目对再次显示给那个用户。但是,这些项目可以与其他未被投票反对的项目一起显示。希望这是从那时起。 这就是我正在尝试的问题,但没有成功

SELECT * FROM (SELECT be.media_id FROM battle_entries as be 
WHERE be.btype=1 AND be.mature=1 AND be.mem_id!=1 
AND NOT EXISTS (SELECT * FROM battle_votes as bv 
WHERE bv.win_id = be.media_id AND bv.mem_id=1 AND bv.lst_id=be.media_id)) s ORDER BY RANDOM() LIMIT 2";
win_id和lst_id是用户选择的一对。我再也不希望这两个项目一起显示给同一个用户,如果该用户在battle_votes表中存在这两个项目,但仍然随机选择了其他没有一起显示的项目

这是桌子

战斗队参赛作品

----------------------------------------------------
| btl_id | mem_id | posted | media_id | active |
----------------------------------------------------
投票

----------------------------------------------------
| btl_id | mem_id | win_id | lst_id | posted |
----------------------------------------------------
如果有更好的方法使用不同的模式,如果不可能的话,我也愿意这样做

编辑: 我最好再解释一遍

我的查询选择了2个用户未投票的随机项目。一旦用户选择一个,将在battle_votes表中创建一个新行。选择的项目ID将输入win_ID列,未选择的项目ID将输入lst_ID列。这是一排。现在,下一次它随机选择显示另外两个项目时,我不希望这两个项目再次成对显示,但每个项目都可以与另一个未进入battle_投票表的项目成对显示。我知道这可能令人困惑


基本上,我不希望同一对再次出现在一起,如果他们选择了任何一个项目

我认为最简单的方法是将行转换为列,选择一对所需的行,然后将其取消拆分:

with cte1 as (
    select
        be.media_id
    from battle_entries as be
    where be.btype = 1 and be.mature = 1 and be.mem_id != 1 
), cte2 as (
    select
        be1.media_id as media_id1,
        be2.media_id as media_id2
    from cte1 as be1
        inner join cte1 as be2 on be2.media_id <> be1.media_id
), cte3 as (
    select c.media_id1, c.media_id2
    from cte2 as c
    where
        not exists
        (
            select *
            from battle_votes as bv 
            where
                bv.mem_id = 1 and
                (
                    bv.win_id = c.media_id1 and bv.lst_id = c.media_id2 or
                    bv.win_id = c.media_id2 and bv.lst_id = c.media_id1
                )
        )
    order by random()
    limit 1
)
select media_id1 as media_id from cte3
union all
select media_id2 as media_id from cte3

您可能需要单独的战斗和胜利表,或者只需要战斗表中的额外列。添加两个ID,但确保较小的ID始终是第一个ID

(btl_id, mem_id, id1, id2, win_id, lst_id, ...)

然后在mem_id、id1、id2上抛出一个唯一的约束/索引。如果你没有使用特别垃圾的ORM,那么你也可以删除btl_id——这是多余的。

你是在白手起家地发明Facebook吗;对于那些没有看过社交网络或没有读过很多关于FBI历史的人来说可能没有意义,这取决于你数据库的复杂性以及可用的选项我从未与Postgre合作过其中一个建议可能是在没有所有条件的情况下按你的方式生成一个随机配对,只需随机订购所有媒体id,并将前2个保存到两个变量中,然后检查这对媒体id是否已按任意顺序出现在battle_投票表中;如果是,扔掉它,生成一对新的。不过,这已经是一些SQL编程了-不确定您是否可以选择编写和运行存储过程。@Helena lol不,我不想重新发明,但我知道您在说什么。我曾考虑过使用两个查询或使用循环do-until循环,但我认为这可能会很昂贵。我可能得走那条路。我似乎已经难倒了一些SQL pro,或者他们不想回答:有趣的这是运行的所有一个查询,包括底部的选择吗?是的,等一下,必须在SQLFIDDLOK中测试它没有问题,也可以通过修改方式跳过unpivot?@Pjack所以如果对已经在投票中,win_id=1,lst_id=2,您不希望以其他方式看到它win_id=2,lst_id=1?没错,我也不希望select以另一种方式为该用户显示它,这就是为什么我还要添加mem_id=x。一旦在投票中,无论顺序是1,2还是2,1,它都不会再次显示为成对。我想你现在明白了。感谢感谢如果我以后需要更改模式,因为我不知道大数据的速度如何,我可能会尝试这种方法,但表不是无限的,并且会定期清除,因此我认为@Roman Pekar的答案会起作用。