In SQL, How can I generate every possible unique combination of 5!56?

匿名 (未验证) 提交于 2019-12-03 01:22:02

问题:

I have a TABLE "elements" with one COLUMN "number", type SMALLINT that contains numbers 1 thru 56. How can I generate unique sets of 5 numbers of every possible combination from 1 to 56, using an SQL statement?

In APL (programming language) a simple dyadic function 5!56 does the trick!

EDIT: In good ole MS-DOS QBASIC, I accomplished it like this:

10  OPEN "C:\5NUMBERS.OUT" FOR OUTPUT ACCESS READ WRITE AS #1 12  LET SER = 0  15  LET E = 56 30      FOR B5 = 5 TO E 40          FOR B4 = 4 TO E 50              FOR B3 = 3 TO E 60                  FOR B2 = 2 TO E 70                      FOR B1 = 1 TO E 80  88  IF B5 = B1 THEN 190 89  IF B5 = B2 THEN 190 90  IF B5 = B3 THEN 190 91  IF B5 = B4 THEN 190  92  IF B4 = B1 THEN 180 93  IF B4 = B2 THEN 180 94  IF B4 = B3 THEN 180  95  IF B3 = B1 THEN 170 96  IF B3 = B2 THEN 170  97  IF B2 = B1 THEN 160  98 LET SER = SER + 1  100 PRINT #1, SER; "|"; 130 PRINT #1, B1; "|"; 131 PRINT #1, B2; "|"; 132 PRINT #1, B3; "|"; 133 PRINT #1, B4; "|"; 134 PRINT #1, B5; "|"; 140 PRINT #1, B1 + B2 + B3 + B4 + B5; "|"  150                     NEXT B1 160                 NEXT B2 170             NEXT B3 180         NEXT B4 190     NEXT B5 205 CLOSE 210 END 220 SYSTEM 

This, by the way, created my load file into an INFORMIX-SQL table

TABLE combos ( seq_id SERIAL, ball_1 SMALLINT, ball_2 SMALLINT, ball_3 SMALLINT, ball_4 SMALLINT, ball_5 SMALLINT, sum    SMALLINT );

I used combos.sum to generate a bell curve graph, showing the count of combinations having the same sum of each element.

回答1:

If you want to include pairs of identical numbers, e.g. (5,5):

SELECT e1.number AS number1       ,e2.number AS number2 FROM   elements e1       ,elements e2 WHERE  e1.number <= e2.number;

If you want to only have different numbers in each pair:

SELECT e1.number AS number1       ,e2.number AS number2 FROM   elements e1       ,elements e2 WHERE  e1.number < e2.number;


回答2:

If by "unique sets" you mean what I think you do (sorry, I don't know APL!), you can write:

SELECT e1.number,   e2.number,   e3.number,   e4.number,   e.number   FROM elements e1, elements e2, elements e3, elements e4, elements e5  WHERE e1.number < e2.number    AND e2.number < e3.number    AND e3.number < e4.number    AND e4.number < e5.number ;

"could this be accomplished without actually having to store the elements in a table?.. i.e. let the server do it without resorting to table I/O? "

Yes, there is an Oracle trick to generate data on the fly, using the hierarchical query and the CTE syntax:

WITH elements AS ( select rownum as number   from dual   connect by level <= 56 ) SELECT e1.number,   e2.number,   e3.number,   e4.number,   e.number   FROM elements e1, elements e2, elements e3, elements e4, elements e5  WHERE e1.number < e2.number    AND e2.number < e3.number    AND e3.number < e4.number    AND e4.number < e5.number ;


回答3:

Not that I would actually use a database for this type of task but, if you were forced to do this under threat of torture or dismemberment, I would look into something like (number shortened to num for formatting purposes):

select a.num, b.num, c.num, d.num, e.num from elements a, elements b, elements c, elements d, elements e where a.num <> b.num and a.num <> c.num and a.num <> d.num and a.num <> e.num   and b.num <> c.num and b.num <> d.num and b.num <> e.num   and c.num <> d.num and c.num <> e.num   and d.num <> e.num

It basically cross joins the table to itself to generate five columns and then filters out those where any of the numbers are identical.

Note that this gives you permutations: (1,2,3,4,5) is distinct from (1,2,3,5,4). If you want combinations (where the order doesn't matter), you would use slightly different clauses:

select a.num, b.num, c.num, d.num, e.num from elements a, elements b, elements c, elements d, elements e where a.num > b.num and b.num > c.num and c.num > d.num and d.num > e.num


回答4:

My FIRST thought would be to do a Cartesian and just make sure that every record is higher than the last so you don't ever get numbers duplicated anywhere. Now this would create something like

1,2,3,4,5 1,2,3,4,6 1,2,3,4,7, etc... but will NEVER have the reverse or mixed such as 6,4,3,2,1 6,2,4,3,1 4,6,1,2,3  as those would already be a "same" set of numbers (more along the lines of lottery style where no same number appears twice)

HOWEVER, if you also wanted duplicates, such as

1,1,1,1,1 1,2,1,2,1 1,2,3,1,1 

Where a number COULD get repeated numbers just change the equality to <= instead of just <.

select       YT1.Number as Num1,       YT2.Number as Num2,       YT3.Number as Num3,       YT4.Number as Num4,       YT5.Number as Num5    from       YourTable YT1          JOIN YourTable YT2             ON YT1.Number < YT2.Number             JOIN YourTable YT3                ON YT2.Number < YT3.Number                JOIN YourTable YT4                   ON YT3.Number < YT4.Number                   JOIN YourTable YT5                      ON YT4.Number < YT5.Number


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!