2011-03-28 5 views
5

SQL 효율성 질문이 있습니다. 이것은 노르웨이 추첨에 관한 것입니다. 그들은 7 개의 숫자와 3 개의 보너스 공을 그립니다.SQL을 사용하여 복권에서 당첨 티켓 확인

나는 모든 그림과 많은 티켓이있는 데이터베이스를 가지고 있습니다. 질문은 가장 효율적인 테이블 구조와 당첨에서 모든 우승 티켓을 얻는 방법입니다.

내 두 가지 테이블입니다 :

LotteryDraw 
    DrawId (int, PK) 
    DrawDate (datetime) 
    MainNumbers (varchar) 
    BonusNumbers (varchar) 
    Main1 (smallint) 
    Main2 (smallint) 
    Main3 (smallint) 
    Main4 (smallint) 
    Main5 (smallint) 
    Main6 (smallint) 
    Main7 (smallint) 
    Bonus1 (smallint) 
    Bonus2 (smallint) 
    Bonus3 (smallint) 

나는 main-와 보너스 숫자의 각 모두 개별적으로뿐만 아니라 정렬 된 순서로 쉼표로 구분 된 문자열을 저장합니다. 내가있어

Similary는 :

LotteryTicket 
    TicketId (int, PK) 
    UserId (int, FK) 
    ValidTill (datetime) 
    MainNumbers (varchar) 
    Main1 (smallint) 
    Main2 (smallint) 
    Main3 (smallint) 
    Main4 (smallint) 
    Main5 (smallint) 
    Main6 (smallint) 
    Main7 (smallint) 

당신은 4 + 1, 5, 6, 6 + 1, 7 정확한 숫자 상 (올바른 주요 번호 + 보너스 번호)를 얻는다. 누구든지 효율적으로 SQL을 작성하는 방법에 대한 훌륭한 아이디어가 있습니다. 추첨 날에 대한 모든 LotteryTickets를 반환 할 것입니다. ValidTill은 티켓이 유효한 마지막 날짜입니다.

현재 C#에서 Linq2Sql을 사용하고 얼음에서 하마의 속도를 보이므로 일부 SQL 전문 지식이 필요합니다.

서버가 중요한 경우 Microsoft SQL Server 2008 R2입니다.

업데이트 : Mark B.의 답변을 수정 한 후 다음 검색어로 끝납니다. 새로운 테이블 LotteryTicketNumber (ticketid, number)를 추가하여 데이터베이스를 약간 정상화해야했습니다.

SELECT LotteryTicket.TicketID, count(LotteryTicket.Numbers) AS MainBalls, (
    SELECT top 1 ltn.Number 
    FROM LotteryTicketNumber ltn 
    WHERE ltn.Number IN (2,4,6) 
    AND ltn.TicketId = LotteryTicket.TicketId 
) As BonusBall 
FROM LotteryTicket 
LEFT JOIN LotteryTicketNumber ON LotteryTicket.TicketId = LotteryTicketNumber.TicketId 
WHERE LotteryTicketNumber.Number IN (13,14,16,23,26,27,30) 
GROUP BY LotteryTicket.TicketID 
HAVING count(LotteryTicketNumber.Number) >= 4 

위의 쿼리는 4 개 이상의 정확한 주 번호가있는 티켓을 모두 반환합니다. 동일한 표에 하나 이상의 보너스 공이 있다면 Bonusball! = NULL 필드도 입력하십시오. 이것은 나를 위해 충분하다.

SELECT LotteryTicket.TicketID, GROUP_CONCAT(LotteryTicketNumbers.number), COUNT(LotteryTicketNumbers.number) AS cnt 
FROM LotteryTicket 
LEFT JOIN LotterYTicketNumbers ON (LotteryTicketNumbers.number IN (winning, numbers, here)) 
GROUP BY LotteryTicket.TicketID 
HAVING cnt >= 3; 

: 당신이 하위 테이블에 번호 목록을 분할하여 데이터를 정상화 할 의향이 있다면, 당신은 하찮게 같은으로 우승자를 결정할 수

+0

12 티켓의 번호는 한 티켓에 12 개의 숫자가 아니며 12 개의 숫자 범위에 7 개의 숫자가 조합 된 것입니다. 모두를 저장할 필요가 없습니다. – cairnz

+0

@cairnz 맞습니다. 그에 따라 편집 됨. – Paaland

+0

@Paaland : 테이블에 어떤 인덱스를 정의 했습니까? –

답변

3

도움을

감사합니다 여기서 '3'은 상을 획득하기 위해 필요한 최소 일치 수를 나타냅니다. "보너스"숫자는 처리되지 않습니다. 동일한 쿼리를 반복하고 보너스 번호가 파생 된 필드에있는 모든 그리기에 플래그를 지정할 수 있습니다.

이것은 테스트되지 않았으므로 머리 꼭대기에서 벗어나므로 일부 구문 오류가있을 수 있습니다.


코멘트 후속은 :

GROUP_CONCAT는 MySQL의 특정 SQL 확장입니다. SQLserver를 사용하고있는 것처럼 보일 수 있으므로이를 제거 할 수 있습니다.

'LottoTicketNumbers'는 테이블을 표준화하기 위해 사용합니다.숫자 1,12,23,44,55와 함께,

LottoTicket: ticketID, drawDate 
LottoTicketNumbers: ticketID, drawNumber 

은 그래서 당신이 4월 1/2011 무승부에 대한 티켓을 가지고 가정 해 봅시다 : 대신 하나의 monolitic "티켓"레코드, 당신은 두 개의 테이블로 분할 , 당신은 같은 것을 끝낼 것 :

LottoTicket: ticketID = 1, drawDate = Apr 1/2011 
LottoTicketNumbers: (1,1), (1,12), (1,23), (1,44), (1,55) 

를이 쿼리 작업을하게 같은 테이블을 구조화, 몇 가지 기본적인 이론과 관계형 데이터베이스의 힘을 사용. 원래의 테이블 구조는 같은

select ... 
where (number1 in (winning, numbers here), number2 in (winning, numbers, here), number3 in (winning, numbers,here), etc.... 

을 일부 무시 무시한 구조를 끝장 정확히 어떤 상품을 당신에게 말할 것이다, 그것은 거의 불가능 당첨 번호의 모든 가능한 순열을 파악하는 데 필요한 비교를 할 수 있습니다 이겼다 (3 일치, 5 + 보너스 일치 등 ...).

예 쿼리 결과 :

이의는 추첨 번호는 1020304050 있습니다 가정 해 봅시다, 당신은 10,20,30,42,53로 티켓을 가지고있다. 5 개의 추첨 번호 중 3 개를 매치하고 $ 10을 획득했습니다. 위의 정규화 된 테이블 구조를 사용하면 같은 테이블에있는 것 : 쿼리가 될 것

LottoTicket: id #203, drawDate: Apr 1/2011 
LottoTicketNumbers: (203, 10), (203, 20), (203, 30), (203, 42), (203, 53) 

SELECT LottoTicket.TicketID, COUNT(LottoTicketNumbers.number) AS cnt 
FROM LottoTicket 
LEFT JOIN LottoTicketNumbers ON (LottoTicketNumbers.number IN (10,20,30,40,50)) 
GROUP BY LottoTicket.TicketID 
HAVING CNT >= 3 

당신 좋겠

203, 10 
203, 20 
203, 30 

의 취득 (그룹 해제) 결과와 그룹화/집계 함수 :

203, 3 // ticket #203 matched 3 numbers. 
+0

나는 이것을 실행하는 데 큰 어려움을 겪고있다. 첫 번째 GROUP_CONCAT은 인식 된 키워드가 아닙니다 (SQL 2008 R2). 두 번째로 LotteryTicketNumbers는 어디에서 왔습니까? – Paaland

3

저는 데이터베이스 전문가는 아니지만 다른 테이블에 데이터를 재구성 할 필요가없는 다소 우아한 솔루션을 생각해 냈습니다. 피벗 테이블을 사용하면 각 숫자에 대해 적절한 수를 반환하도록 SQL을 얻을 수 있습니다.

먼저 피벗 테이블 (쿼리에서 MS SQL Server 오류가 발생하기 때문에 피벗의 이름을 지정하지 마십시오). 이것은 int 형, 1 차 키의 1 개의 열을 가지는 단순한 테이블이다). 1에서 100까지의 행이있는 데이터를 보유하고 있습니다. 가장 높은 복권 번호만큼 많은 숫자가 필요합니다. 더 이상은 괜찮습니다.

PVT Structure: i(int,primary key) 

PVT Data: (1) (2) (3) .... (100) 

플로리다 복권 6 번호, 파워 볼 없음, 53 번호에 대해이 예제를 수행합니다.

당신은 LotteryTicket 테이블,

LotteryTicket: ID, Number, N1, N2, N3, N4, N5, N6 

샘플 데이터 같은 것을 가지고

(1), (1-2-3-4-5-6), (1), ((2), (1-2-3-15-18-52), (1), (2), (3), (3), (4), (5)), (15), (18), (52)

Query/Stored pr ocedure : [같은 로또 번호를 전달합니다 1-2-3-20-30-33 또는 떠날 기본 PARAMS (예)] LotteryTickets 내 예를 들어

MatchFloridaLottery 
    (
     @p1 int = 1, 
     @p2 int = 2, 
     @p3 int = 3, 
     @p4 int = 4, 
     @p5 int = 5, 
     @p6 int = 6, 
     @minmatches int = 2 
    ) 

AS 



SELECT t.id, COUNT(p.i) numbermatch 
FROM LotteryTicket t, pvt p 
WHERE 
(n1 IN (@p1,@p2,@p3,@P4,@p5,@p6) AND t.n1=p.i) 
or 
(n2 IN (@p1,@p2,@p3,@P4,@p5,@p6) AND t.n2=p.i) 
or 
(n3 IN (@p1,@p2,@p3,@P4,@p5,@p6) AND t.n3=p.i) 
or 
(n4 IN (@p1,@p2,@p3,@P4,@p5,@p6) AND t.n4=p.i) 
or 
(n5 IN (@p1,@p2,@p3,@P4,@p5,@p6) AND t.n5=p.i) 
or 
(n6 IN (@p1,@p2,@p3,@P4,@p5,@p6) AND t.n6=p.i) 

group by n.id 
HAVING COUNT(p.i) > @minmatches 

내가 얻을 :

ID  NumberMatch (count of numbers that matched) 

1   6 

2   3 

피봇 테이블을 사용하면 쿼리에서 우승 한 번호와 일치하는 각 열에 대한 행을 반환 할 수 있습니다.이 행을 id로 그룹화하고 피벗 테이블 (열 i)에서 반환 한 총 행 수를 계산합니다. 이는 총 일치 수입니다 이기는 수에. 그렇습니다. 쿼리는 꽤 실제적이지는 않지만 작동하며 별도의 테이블과 행의 모든 ​​작업을 수행하지 않아도됩니다. 필요에 따라 다른 게임을 수정하십시오.