문제

두 객체를 표시하는 페이지가 있는데 사용자는이 중 하나를 선택합니다. MSSQL 데이터베이스에 선호도와 조합을 기록하고 다음과 같은 데이터를 저장하게됩니다.

UserId=1, BetterObjectId=1, WorseObjectId=2

이제 나는 물체 (1,2 / 2,1)의 조합을 다시 보여주지 않겠다.

그렇다면 이전에 본 조합을 제외한 사용자를 보여주기 위해 임의의 조합을 어떻게 생성합니까?

이것은 정말 간단한 질문이어야하지만 대부분의 프로그래머처럼 나는 수면과 커피가 부족하므로 도움을 주셔서 감사합니다 :-)

그만큼 매우 순진한 접근 방식은 이와 같은 것입니다 (그리고이 기능에 대한 모든 호출은 사용자가 NCR만큼 여러 번 등급을 매겼는지 확인하여 N은 항목 수이고 R은 2) : :

public List<Item> GetTwoRandomItems(int userId)
{
    Item i = null, i2 = null;
    List<Item> r = null;

    while (i == null || i2 == null)
    {
        r = GetTwoRandomItemsRaw();
        i = r[0];
        i2 = r[1];
        if (GetRating(i.Id, i2.Id, userId) != null) /* Checks if viewed */
        {
            i = null;
            i2 = null;
        }
    }
    return r;
}

private List<Item> GetTwoRandomItemsRaw()
{
    return Items.ToList().OrderBy(i => Guid.NewGuid()).Take(2).ToList();
}

편집

일부 SQL을 사용하면 완료되지 않은 모든 항목의 목록을 생성 할 수 있습니다 (즉, 사용자가 보지 못한 항목과 관련된 조합이 있습니다). 특히 유용하지 않다고 생각합니다.

또한 2 개의 임의의 항목을 선택하기 전에 가능한 모든 가능한 조합을 생성하고 이미 본 조합을 제거하는 것을 상상할 수 있지만 이것은 또 다른 끔찍한 솔루션입니다.

가능성 (큰 n에 대한 메모리 집약적)은 가능한 모든 조합을 생성하고 CombinSID를 등급에 저장하는 것입니다. 그런 다음 조합의 대칭 관계를 반영하기 위해 약간의 변경 사항을 사용하여 CombinitID가없는 모든 조합을 선택할 수 있습니다 (UserID = X가있는 등급에서 CombinSID).

도움이 되었습니까?

해결책

Table Item: ItemId
Table Rating: UserId, ItemId1, ItemId2, WinnerId

등급 테이블에 itemid1 <itemid2가 필요한 경우 등급 테이블을 한 번만 확인하면됩니다.

var pair = db.Items.Join(db.Items,
  i1 => i1.ItemId,
  i2 => i2.ItemId,
  (i1, i2) => new {i1, i2}
)  //produce all pairs
.Where(x => x.i1.ItemId < x.i2.ItemId) //filter diagonal to unique pairs
.Where(x => 
  !db.Ratings
  .Where(r => r.UserId == userId
    && r.ItemId1 == x.i1.ItemId
    && r.ItemId2 == x.i2.ItemId)
  .Any() //not any ratings for this user and pair
)
.OrderBy(x => db.GetNewId()) //in-database random ordering
.First();  // just give me the first one

return new List<Item>() {pair.i1, pair.i2 };

여기에 있습니다 블로그 "무작위"를 데이터베이스로 번역하는 것.

다른 팁

한 가지 해결책은 다음과 같습니다.

SELECT TOP 1 i.id item1, i2.id item2 from item i, item i2 
WHERE i.id <> i2.id 
AND (SELECT COUNT(*) FROM Rating WHERE userId=@userId AND FK_ItemBetter=i.id AND FK_ItemWorse=i2.id) = 0
AND (SELECT COUNT(*) FROM Rating WHERE userId=@userId AND FK_ItemBetter=i2.id AND FK_ItemWorse=i.id) = 0
ORDER BY NEWID()

나는 그것을 몰랐다 크로스 조인 이전 테이블에서 여러 가지를 나열하는 방법.

사용 가능한 항목 목록이 데이터베이스에 있다고 가정하면 데이터베이스 에서이 문제를 완전히 처리합니다. 당신은 무엇이든 이미 데이터베이스를 치고 있습니다. 왜 그곳에서 그것을 끝내지 않겠습니까?

모든 물체를 대기열이나 스택에 넣은 다음 비어있을 때까지 2와 2를 끄는 것은 어떻습니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top