1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu SQL Puzzles & Answers- P8 pdf

40 462 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề SQL Puzzles & Answers
Trường học Unknown University
Chuyên ngành Computer Science
Thể loại Tài liệu
Năm xuất bản Unknown Year
Thành phố Unknown City
Định dạng
Số trang 40
Dung lượng 368,69 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

CREATE TABLE SudokuGridi INTEGER NOT NULL CHECK i BETWEEN 1 AND 9, j INTEGER NOT NULL CHECK j BETWEEN 1 AND 9, val INTEGER NOT NULL CHECK val BETWEEN 1 AND 9, region_nbr INTEGER NOT NU

Trang 1

being, so we should be safe A quick way is to use your auxiliary Sequence table.

SELECT P.product_id FROM PriceByAge AS P, Sequence AS S WHERE S.seq BETWEEN P.low_age AND P.high_age AND S.seq <= 150

GROUP BY P.product_idHAVING COUNT(seq) = 150;

Trang 2

I thought that Sudoku, the current puzzle fad, would be a good SQL programming problem You start with a 9×9 grid that is further divided into nine 3 ×3 regions Some of the cells will have a digit from 1 to 9 in them at the start of the puzzle Your goal is to fill in all the cells with more digits such that each row, column, and region contains one and only one instance of each digit

Strangely, the puzzle appeared in the United States in 1979, then caught on in Japan in 1986 and became an international fad in 2005 Most newspapers today carry a daily Sudoku

How can we do this in SQL? Well we can start by modeling the grid as

an (i, j) array with a value in the cell The first attempt usually does not have the region information as one of the columns The regions do not have names in the puzzle, so we need a way to give them names

CREATE TABLE SudokuGrid(i INTEGER NOT NULL CHECK (i BETWEEN 1 AND 9),

j INTEGER NOT NULL CHECK (j BETWEEN 1 AND 9), val INTEGER NOT NULL

CHECK (val BETWEEN 1 AND 9), region_nbr INTEGER NOT NULL, PRIMARY KEY (i, j, val));

Now we need to fill it Each (i, j) cell needs to start with all nine digits, so we build a table of the digits 1 to 9 and do CROSS JOINs But how do we get a region number?

An obvious name would be the position of the region by (x, y)

coordinates, where x = {1, 2, 3} and y = {1, 2, 3} We can then make them into one number by making x the tens place and y the units place,

so we get {11,12, 13, 21, 22, 23, 31, 32, 33} for the regions The math for this depends on integer arithmetic, but it is not really hard

INSERT INTO SudokuGrid (i, j, val, region_nbr)SELECT D1.d, D2.d, D3.d,

10*((D1.d+2)/3) + ((D2.d+2)/3) AS region_nbr FROM Digits AS D1

CROSS JOIN Digits AS D2

Trang 3

CROSS JOIN Digits AS D3;

We will need a procedure to insert the known values and clear out that value in the rows, columns, and regions As we remove more and more values, we hope to get a table with 81 cells that is the unique solution for the puzzle

Answer #1

The first attempt is usually to write three delete statements, one for rows, one for columns, and one for the region

BEGINDELETE FROM SudokuGrid rowsWHERE :my_i = i

AND :my_j <> j AND :my_val = val;

DELETE FROM SudokuGrid columnsWHERE :my_i <> i

AND :my_j = j AND :my_val = val;

DELETE FROM SudokuGrid regionWHERE i <> :my_i

AND j <> :my_j AND region_nbr = 10*((:my_i+2)/3) + ((:my_j+2)/3) AND :my_val = val);

Trang 4

AND region_nbr = 10*((:my_i+2)/3) + ((:my_j+2)/3) AND :my_val = val);

Those nested ORs are ugly! The expression (:my_val = val) appears twice Get a drink, step back, and consider that the (i, j) pairs can relate to our input in one of four mutually exclusive ways, which require that we remove a value from a cell or leave it That implies a CASE

expression instead of the nested ANDs and ORs

DELETE FROM SudokuGrid WHERE CASE WHEN :my_i = i AND :my_j = j my cell THEN 'Keep'

WHEN :my_i = i AND :my_j <> j row THEN 'Delete'

WHEN :my_i <> i AND :my_j = j column THEN 'Delete'

WHEN i <> :my_i AND j <> :my_j square AND region_nbr

= 10*(:my_i+2)/3) + (:my_j+2)/3) THEN 'Delete'

ELSE NULL END = 'Delete' AND :my_val = val);

Answer #3

Test it and find out that this is wrong!! We need to pay special attention

to the cell where we know the value; that means two cases

DELETE FROM SudokuGrid WHERE CASE WHEN :my_i = i AND :my_j = j AND my_val = val THEN 'Keep'

WHEN :my_i = i AND :my_j = j AND my_val <> val THEN 'Delete'

WHEN :my_i = i AND :my_j <> j row THEN 'Delete'

WHEN :my_i <> i AND :my_j = j column THEN 'Delete'

WHEN i <> :my_i AND j <> :my_j square AND region_nbr

= 10*(:my_i+2)/3) + (:my_j+2)/3) THEN 'Delete'

Trang 5

ELSE NULL END = 'Delete' AND :my_val = val);

The next improvement might be to put the known cells into their own table so we have a history of the puzzle But let’s leave that as a problem for the reader

Trang 6

This is a classic programming problem from procedural language classes The setup is fairly simple; you have a set of potential husbands and an equally sized set of potential wives We want to pair them up into stable marriages

What is a stable marriage? In 25 words or less, a marriage in which

neither partner can do better You have a set of n men and a set of n

women All the men have a preference scale for all the women that ranks

them from 1 to n without gaps or ties The women have the same ranking

system for the men

The goal is to pair off the men and women into n marriages such that

there is no pair in your final arrangement where Mr X and Ms Y are matched to each other when they both would rather be matched to someone else

For example, let’s assume the husbands are (“Joe Celko,” “Brad Pitt”) and the wives are (“Jackie Celko,” “Angelina Jolie”) If Jackers got matched to Mr Pitt, she would be quite happy And I would enjoy Ms Jolie’s company However, Mr Pitt and Ms Jolie can both do better than

us Once they are paired up they will stay that way, leaving Jackers and I still wed

The classic Stable Marriage algorithms usually are based on backtracking These algorithms try a combination of couples, and then attempt to fix any unhappy matches When the algorithm hits on a situation where nobody can improve their situation, they stop and give

an answer.

Two important things to know about this problem: (1) there is always a solution, and (2) there is often more than one solution Doing this in SQL is really hard because SQL does not backtrack

Remember that a stable marriage is not always a happy marriage In fact, in this problem, while there is always at least one arrangement of stable marriages in any set, you most often find many different pairings that produce a set of stable marriages Each set of marriages will tend to maximize either the happiness of the men or the women

Let’s show a small example in SQL with four couples:

CREATE TABLE Husbands(man CHAR(5) NOT NULL, woman CHAR(5) NOT NULL, ranking INTEGER NOT NULL CHECK (ranking > 0),

Trang 7

PRIMARY KEY (man, woman));

INSERT INTO Husbands VALUES ('Abe', 'Joan', 1);

INSERT INTO Husbands VALUES ('Abe', 'Kathy', 2);

INSERT INTO Husbands VALUES ('Abe', 'Lynn', 3);

INSERT INTO Husbands VALUES ('Abe', 'Molly', 4);

INSERT INTO Husbands VALUES ('Bob', 'Joan', 3);

INSERT INTO Husbands VALUES ('Bob', 'Kathy', 4);

INSERT INTO Husbands VALUES ('Bob', 'Lynn', 2);

INSERT INTO Husbands VALUES ('Bob', 'Molly', 1);

INSERT INTO Husbands VALUES ('Chuck', 'Joan', 3); INSERT INTO Husbands VALUES ('Chuck', 'Kathy', 4); INSERT INTO Husbands VALUES ('Chuck', 'Lynn', 2); INSERT INTO Husbands VALUES ('Chuck', 'Molly', 1);

INSERT INTO Husbands VALUES ('Dave', 'Joan', 2);

INSERT INTO Husbands VALUES ('Dave', 'Kathy', 1); INSERT INTO Husbands VALUES ('Dave', 'Lynn', 3);

INSERT INTO Husbands VALUES ('Dave', 'Molly', 4);

CREATE TABLE Wives (woman CHAR(5) NOT NULL, man CHAR(5) NOT NULL, ranking INTEGER NOT NULL CHECK (ranking > 0), PRIMARY KEY (man, woman));

INSERT INTO Wives VALUES ('Joan', 'Abe', 1);

INSERT INTO Wives VALUES ('Joan', 'Bob', 3);

INSERT INTO Wives VALUES ('Joan', 'Chuck', 2);

INSERT INTO Wives VALUES ('Joan', 'Dave', 4);

INSERT INTO Wives VALUES ('Kathy', 'Abe', 4);

INSERT INTO Wives VALUES ('Kathy', 'Bob', 2);

INSERT INTO Wives VALUES ('Kathy', 'Chuck', 3);

INSERT INTO Wives VALUES ('Kathy', 'Dave', 1);

INSERT INTO Wives VALUES ('Lynn', 'Abe', 1);

INSERT INTO Wives VALUES ('Lynn', 'Bob', 3);

INSERT INTO Wives VALUES ('Lynn', 'Chuck', 4);

INSERT INTO Wives VALUES ('Lynn', 'Dave', 2);

INSERT INTO Wives VALUES ('Molly', 'Abe', 3);

Trang 8

INSERT INTO Wives VALUES ('Molly', 'Bob', 4);

INSERT INTO Wives VALUES ('Molly', 'Chuck', 1);

INSERT INTO Wives VALUES ('Molly', 'Dave', 2);

The pairing of:

('Abe', 'Lynn')('Bob', 'Joan')('Chuck', 'Molly')('Dave', 'Kathy')

does not work There is a “blocking pair” in ('Abe', 'Joan') Abe is Joan’s first choice and he is her first choice, as shown by the rows:

Wives ('Joan', 'Abe', 1)Husbands ('Abe', 'Joan', 1)

but they are matched to others A simple swap will give us a stable situation:

('Abe', 'Joan')('Bob', 'Lynn')('Chuck', 'Molly')('Dave', 'Kathy')

If you use a backtracking algorithm, you do not have to generate all possible marriage sets Once you found a blocking pair, you would never have to create it again This is considerably faster than the combinatory explosion that SQL must generate and filter The only advantage with SQL—and it is weak—is that the algorithms for this problem will usually stop at the first success They do not generate the full solution set, as SQL does

This answer is from Richard Romley Simply explained, it generates all possible marriages and filters out the failures But there are some neat little optimizing tricks in the code.

DROP TABLE Wife_perms;

CREATE TABLE Wife_perms(wife CHAR(5) NOT NULL PRIMARY KEY,tally INTEGER NOT NULL);

INSERT INTO Wife_perms VALUES ('Joan', 1);

Trang 9

INSERT INTO Wife_perms VALUES ('Kathy', 2);

INSERT INTO Wife_perms VALUES ('Lynn', 4);

INSERT INTO Wife_perms VALUES ('Molly', 8);

Answer #1

The query for finding stable marriages is:

SELECT W1.wife AS abe_wife, W2.wife AS bob_wife, W3.wife AS check_wife, W4.wife AS dave_wifeFROM Wife_perms AS W1, Wife_perms AS W2, Wife_perms AS W3, Wife_perms AS W4

WHERE (W1.tally + W2.tally + W3.tally + W4.tally) = 15 AND NOT EXISTS

AND W1.woman = W2.womanAND W1.ranking > W2.rankingAND (W1.man || W1.woman) IN ('Abe' || W1.wife, 'Bob' || W2.wife,'Chuck' || W3.wife, 'Dave' || W4.wife));

The first predicate generates all the permutations of wives in the husband columns and the EXISTS() checks for “blocking pairs” in the row This query will take some time to run, especially on a small

machine, and it will break down when you have a value of n too large for

the permutation trick

The other optimization trick is the list of concatenated strings to see that the blocking pair is in the row that was just constructed A shorter version of this trick is replacing

SELECT * FROM Foo as F1, Bar as B1 WHERE F1.city = B1.city AND F1.state = B1.state;

Trang 10

with

SELECT * FROM Foo as F1, Bar as B1 WHERE F1.city || F1.state = B1.city || B1.state;

to speed up a query I will rationalize that the concatenated name is atomic because it has meaning in itself that would be destroyed if it is split apart Things like (longitude, latitude) pairs are also atomic in this sense

There were only 4! (= 24) possible marriage collections, so this ran pretty fast, even on a small machine Now extend the problem to a set of couples where (n = 8); you now have 8! (= 40,320) possible marriage collections And only a small number of the rows will be in the final answer set

Answer #2

Here is the code for the Stable Marriages problem with n = 8:

CREATE TABLE Husbands(man CHAR(2) NOT NULL, woman CHAR(2) NOT NULL, ranking INTEGER NOT NULL CHECK (ranking > 0), PRIMARY KEY (man, woman));

CREATE TABLE Wives(woman CHAR(2) NOT NULL, man CHAR(2) NOT NULL, ranking INTEGER NOT NULL CHECK (ranking > 0),PRIMARY KEY (woman, man));

INSERT INTO Husbands VALUES ('h1', 'w1', 5);

INSERT INTO Husbands VALUES ('h1', 'w2', 2);

INSERT INTO Husbands VALUES ('h1', 'w3', 6);

INSERT INTO Husbands VALUES ('h1', 'w4', 8);

INSERT INTO Husbands VALUES ('h1', 'w5', 4);

INSERT INTO Husbands VALUES ('h1', 'w6', 3);

INSERT INTO Husbands VALUES ('h1', 'w7', 1);

INSERT INTO Husbands VALUES ('h1', 'w8', 7);

Trang 11

INSERT INTO Husbands VALUES ('h2', 'w1', 6);

INSERT INTO Husbands VALUES ('h2', 'w2', 3);

INSERT INTO Husbands VALUES ('h2', 'w3', 2);

INSERT INTO Husbands VALUES ('h2', 'w4', 1);

INSERT INTO Husbands VALUES ('h2', 'w5', 8);

INSERT INTO Husbands VALUES ('h2', 'w6', 4);

INSERT INTO Husbands VALUES ('h2', 'w7', 7);

INSERT INTO Husbands VALUES ('h2', 'w8', 5);

INSERT INTO Husbands VALUES ('h3', 'w1', 4);

INSERT INTO Husbands VALUES ('h3', 'w2', 2);

INSERT INTO Husbands VALUES ('h3', 'w3', 1);

INSERT INTO Husbands VALUES ('h3', 'w4', 3);

INSERT INTO Husbands VALUES ('h3', 'w5', 6);

INSERT INTO Husbands VALUES ('h3', 'w6', 8);

INSERT INTO Husbands VALUES ('h3', 'w7', 7);

INSERT INTO Husbands VALUES ('h3', 'w8', 5);

INSERT INTO Husbands VALUES ('h4', 'w1', 8);

INSERT INTO Husbands VALUES ('h4', 'w2', 4);

INSERT INTO Husbands VALUES ('h4', 'w3', 1);

INSERT INTO Husbands VALUES ('h4', 'w4', 3);

INSERT INTO Husbands VALUES ('h4', 'w5', 5);

INSERT INTO Husbands VALUES ('h4', 'w6', 6);

INSERT INTO Husbands VALUES ('h4', 'w7', 7);

INSERT INTO Husbands VALUES ('h4', 'w8', 2);

INSERT INTO Husbands VALUES ('h5', 'w1', 6);

INSERT INTO Husbands VALUES ('h5', 'w2', 8);

INSERT INTO Husbands VALUES ('h5', 'w3', 2);

INSERT INTO Husbands VALUES ('h5', 'w4', 3);

INSERT INTO Husbands VALUES ('h5', 'w5', 4);

INSERT INTO Husbands VALUES ('h5', 'w6', 5);

INSERT INTO Husbands VALUES ('h5', 'w7', 7);

INSERT INTO Husbands VALUES ('h5', 'w8', 1);

INSERT INTO Husbands VALUES ('h6', 'w1', 7);

INSERT INTO Husbands VALUES ('h6', 'w2', 4);

INSERT INTO Husbands VALUES ('h6', 'w3', 6);

INSERT INTO Husbands VALUES ('h6', 'w4', 5);

INSERT INTO Husbands VALUES ('h6', 'w5', 3);

INSERT INTO Husbands VALUES ('h6', 'w6', 8);

INSERT INTO Husbands VALUES ('h6', 'w7', 2);

INSERT INTO Husbands VALUES ('h6', 'w8', 1);

INSERT INTO Husbands VALUES ('h7', 'w1', 5);

INSERT INTO Husbands VALUES ('h7', 'w2', 1);

Trang 12

INSERT INTO Husbands VALUES ('h7', 'w3', 4);

INSERT INTO Husbands VALUES ('h7', 'w4', 2);

INSERT INTO Husbands VALUES ('h7', 'w5', 7);

INSERT INTO Husbands VALUES ('h7', 'w6', 3);

INSERT INTO Husbands VALUES ('h7', 'w7', 6);

INSERT INTO Husbands VALUES ('h7', 'w8', 8);

INSERT INTO Husbands VALUES ('h8', 'w1', 2);

INSERT INTO Husbands VALUES ('h8', 'w2', 4);

INSERT INTO Husbands VALUES ('h8', 'w3', 7);

INSERT INTO Husbands VALUES ('h8', 'w4', 3);

INSERT INTO Husbands VALUES ('h8', 'w5', 6);

INSERT INTO Husbands VALUES ('h8', 'w6', 1);

INSERT INTO Husbands VALUES ('h8', 'w7', 5);

INSERT INTO Husbands VALUES ('h8', 'w8', 8);

INSERT INTO Wives VALUES ('w1', 'h1', 6);

INSERT INTO Wives VALUES ('w1', 'h2', 3);

INSERT INTO Wives VALUES ('w1', 'h3', 7);

INSERT INTO Wives VALUES ('w1', 'h4', 1);

INSERT INTO Wives VALUES ('w1', 'h5', 4);

INSERT INTO Wives VALUES ('w1', 'h6', 2);

INSERT INTO Wives VALUES ('w1', 'h7', 8);

INSERT INTO Wives VALUES ('w1', 'h8', 5);

INSERT INTO Wives VALUES ('w2', 'h1', 4);

INSERT INTO Wives VALUES ('w2', 'h2', 8);

INSERT INTO Wives VALUES ('w2', 'h3', 3);

INSERT INTO Wives VALUES ('w2', 'h4', 7);

INSERT INTO Wives VALUES ('w2', 'h5', 2);

INSERT INTO Wives VALUES ('w2', 'h6', 5);

INSERT INTO Wives VALUES ('w2', 'h7', 6);

INSERT INTO Wives VALUES ('w2', 'h8', 1);

INSERT INTO Wives VALUES ('w3', 'h1', 3);

INSERT INTO Wives VALUES ('w3', 'h2', 4);

INSERT INTO Wives VALUES ('w3', 'h3', 5);

INSERT INTO Wives VALUES ('w3', 'h4', 6);

INSERT INTO Wives VALUES ('w3', 'h5', 8);

INSERT INTO Wives VALUES ('w3', 'h6', 1);

INSERT INTO Wives VALUES ('w3', 'h7', 7);

INSERT INTO Wives VALUES ('w3', 'h8', 2);

INSERT INTO Wives VALUES ('w4', 'h1', 8);

INSERT INTO Wives VALUES ('w4', 'h2', 2);

INSERT INTO Wives VALUES ('w4', 'h3', 1);

INSERT INTO Wives VALUES ('w4', 'h4', 3);

Trang 13

INSERT INTO Wives VALUES ('w4', 'h5', 7);

INSERT INTO Wives VALUES ('w4', 'h6', 5);

INSERT INTO Wives VALUES ('w4', 'h7', 4);

INSERT INTO Wives VALUES ('w4', 'h8', 6);

INSERT INTO Wives VALUES ('w5', 'h1', 3);

INSERT INTO Wives VALUES ('w5', 'h2', 7);

INSERT INTO Wives VALUES ('w5', 'h3', 2);

INSERT INTO Wives VALUES ('w5', 'h4', 4);

INSERT INTO Wives VALUES ('w5', 'h5', 5);

INSERT INTO Wives VALUES ('w5', 'h6', 1);

INSERT INTO Wives VALUES ('w5', 'h7', 6);

INSERT INTO Wives VALUES ('w5', 'h8', 8);

INSERT INTO Wives VALUES ('w6', 'h1', 2);

INSERT INTO Wives VALUES ('w6', 'h2', 1);

INSERT INTO Wives VALUES ('w6', 'h3', 3);

INSERT INTO Wives VALUES ('w6', 'h4', 6);

INSERT INTO Wives VALUES ('w6', 'h5', 8);

INSERT INTO Wives VALUES ('w6', 'h6', 7);

INSERT INTO Wives VALUES ('w6', 'h7', 5);

INSERT INTO Wives VALUES ('w6', 'h8', 4);

INSERT INTO Wives VALUES ('w7', 'h1', 6);

INSERT INTO Wives VALUES ('w7', 'h2', 4);

INSERT INTO Wives VALUES ('w7', 'h3', 1);

INSERT INTO Wives VALUES ('w7', 'h4', 5);

INSERT INTO Wives VALUES ('w7', 'h5', 2);

INSERT INTO Wives VALUES ('w7', 'h6', 8);

INSERT INTO Wives VALUES ('w7', 'h7', 3);

INSERT INTO Wives VALUES ('w7', 'h8', 7);

INSERT INTO Wives VALUES ('w8', 'h1', 8);

INSERT INTO Wives VALUES ('w8', 'h2', 2);

INSERT INTO Wives VALUES ('w8', 'h3', 7);

INSERT INTO Wives VALUES ('w8', 'h4', 4);

INSERT INTO Wives VALUES ('w8', 'h5', 5);

INSERT INTO Wives VALUES ('w8', 'h6', 6);

INSERT INTO Wives VALUES ('w8', 'h7', 1);

INSERT INTO Wives VALUES ('w8', 'h8', 3);

wife permutations CREATE TABLE Wife_perms(wife CHAR(2) NOT NULL PRIMARY KEY, tally INTEGER NOT NULL);

Trang 14

INSERT INTO Wife_perms VALUES ('w1', 1);

INSERT INTO Wife_perms VALUES ('w2', 2);

INSERT INTO Wife_perms VALUES ('w3', 3);

INSERT INTO Wife_perms VALUES ('w4', 4);

INSERT INTO Wife_perms VALUES ('w5', 5);

INSERT INTO Wife_perms VALUES ('w6', 6);

INSERT INTO Wife_perms VALUES ('w7', 7);

INSERT INTO Wife_perms VALUES ('w8', 8);

This query produces the correct results:

SELECT W1.wife AS h1, W2.wife AS h2, W3.wife AS h3, W4.wife AS h4, W5.wife AS h5, W6.wife AS h6, W7.wife AS h7, W8.wife AS h8

FROM Wife_perms AS W1, Wife_perms AS W2, Wife_perms AS W3, Wife_perms AS W4, Wife_perms AS W5, Wife_perms AS W6, Wife_perms AS W7 , Wife_perms AS W8

WHERE (W1.tally + W2.tally + W3.tally + W4.tally + W5.tally + W6.tally + W7.tally + W8.tally) = 255AND NOT EXISTS

(SELECT *FROM Husbands AS H1, Husbands AS H2, Wives AS W1, Wives AS W2

WHERE H1.man = H2.manAND H1.ranking > H2.rankingAND (H1.man || H1.woman) IN ('h1' || H1.wife, 'h2' || H2.wife, 'h3' || H3.wife, 'h4' || H4.wife, 'h5' || H5.wife, 'h6' || H6.wife, 'h7' || H7.wife, 'h8' || H8.wife)AND H2.woman = W1.woman

AND W1.woman = W2.womanAND W1.ranking > W2.rankingAND (W1.man || W1.woman) IN ('h1' || H1.wife, 'h2' || H2.wife, 'h3' || H3.wife, 'h4' || H4.wife, 'h5' || H5.wife, 'h6' || H6.wife, 'h7' || H7.wife, 'h8' || H8.wife));

The final results are:

Trang 15

h1 h2 h3 h4 h5 h6 h7 h8

================================

w2 w4 w3 w1 w7 w5 w8 w6w2 w4 w3 w8 w1 w5 w7 w6w3 w6 w4 w1 w7 w5 w8 w2w3 w6 w4 w8 w1 w5 w7 w2w6 w3 w4 w1 w7 w5 w8 w2w6 w3 w4 w8 w1 w5 w7 w2w6 w4 w3 w1 w7 w5 w8 w2w6 w4 w3 w8 w1 w5 w7 w2w7 w4 w3 w8 w1 w5 w2 w6

This example was taken from Niklaus Wirth’s book (see the references list at the end of this puzzle).

Answer #3

The key was to maximize the performance of the NOT EXISTS test in the final SELECT Unstable is a table of the unstable relationships—in a form designed to be used as the object of the LIKE clause in the final query

CREATE TABLE Unstable (bad_marriage CHAR(16) NOT NULL);

INSERT INTO UnstableSELECT DISTINCT CASE WHEN W.man = 'h1' THEN W.woman WHEN Y.man = 'h1' THEN Y.woman ELSE ' ' END || CASE WHEN W.man = 'h2' THEN W.woman WHEN Y.man = 'h2' THEN Y.woman ELSE ' ' END || CASE WHEN W.man = 'h3' THEN W.woman WHEN Y.man = 'h3' THEN Y.woman ELSE ' ' END || CASE WHEN W.man = 'h4' THEN W.woman WHEN Y.man = 'h4' THEN Y.woman ELSE ' ' END || CASE WHEN W.man = 'h5' THEN W.woman WHEN Y.man = 'h5' THEN Y.woman ELSE ' ' END

Trang 16

|| CASE WHEN W.man = 'h6' THEN W.woman WHEN Y.man = 'h6' THEN Y.woman ELSE ' ' END || CASE WHEN W.man = 'h7' THEN W.woman WHEN Y.man = 'h7' THEN Y.woman ELSE ' ' END || CASE WHEN W.man = 'h8' THEN W.woman WHEN Y.man = 'h8' THEN Y.woman ELSE ' ' END FROM Husbands AS W, Husbands AS X, Wives AS Y, Wives AS Z

WHERE W.man = X.man AND W.ranking > X.ranking AND X.woman = Y.woman AND Y.woman = Z.woman AND Y.ranking > Z.ranking AND Z.man = W.man

SELECT A.name AS h1, B.name AS h2, C.name AS h3, D.name AS h4,

E.name AS h5, F.name AS h6, G.name AS h7, H.name AS h8

FROM wife_hdr AS a, wife_hdr AS b, wife_hdr AS c, wife_hdr

AS d, wife_hdr AS e, wife_hdr AS f, wife_hdr AS g, wife_hdr

AS h WHERE B.name NOT IN (A.name) AND C.name NOT IN (A.name, B.name) AND D.name NOT IN (A.name, B.name, C.name) AND E.name NOT IN (A.name, B.name, C.name, D.name) AND F.name NOT IN (A.name, B.name, C.name, D.name, E.name)

AND G.name NOT IN (A.name, B.name, C.name, D.name, E.name, F.name)

AND H.name NOT IN (A.name, B.name, C.name, D.name, E.name, F.name, G.name)

AND NOT EXISTS (SELECT * FROM Unstable WHERE A.name || B.name || C.name || D.name || E.name || F.name || G.name || H.name LIKE bad_marriage)

Trang 17

h1 h2 h3 h4 h5 h6 h7 h8 w3 w6 w4 w8 w1 w5 w7 w2w6 w4 w3 w8 w1 w5 w7 w2w6 w3 w4 w8 w1 w5 w7 w2w3 w6 w4 w1 w7 w5 w8 w2w6 w4 w3 w1 w7 w5 w8 w2w6 w3 w4 w1 w7 w5 w8 w2w7 w4 w3 w8 w1 w5 w2 w6w2 w4 w3 w8 w1 w5 w7 w6w2 w4 w3 w1 w7 w5 w8 w6

When Richard timed this, he got 40,000 rows in 4 seconds at an average throughput of around 10,000 rows per second I don’t think I’m going to do any better than that

The first predicate generates all the permutations of wives in the husband columns, and the EXISTS() checks for blocking pairs in the row This query will take some time to run, especially on a small

machine, and it will break down when you have a value of n too large for

the permutation trick

Trang 18

Gusfierld, Dan, and Irving, Robert W., The Stable Marriage Problem: Structure & Algorithms, ISBN 0-262-07118-5

Knuth, Donald E., CRM Proceedings & Lecture Notes, Vol #10, “Stable

Marriage and Its Relation to Other Combinatorial Problems,” ISBN 0-8218-0603-3

This booklet, which reproduces seven expository lectures given by the author in November 1975, is a gentle introduction to the analysis of algorithms using the beautiful theory of stable marriages as a vehicle to explain the basic paradigms of that subject

Wirth, Niklaus, Section 3.6, Algorithms + Data Structures = Programs,

ISBN 0-13-022418-9

This section gives an answer in Pascal and a short analysis of the algorithm In particular, I used his data for my example He gives several answers that give a varying “degrees of happiness” for husbands and wives

Trang 19

Suppose a man randomly runs to the bus station and catches the next bus leaving the station Assume there are only two bus routes in this town, and call them “A” and “B.” The schedule for each route spaces the bus trips one hour apart Your first thought may be that the random traveler would spend approximately equal time on both routes, but the truth is that he spends far more time on route A than on route B Why? The A bus leaves on the hour, and the B bus leaves at five minutes after the hour In order to catch the B bus, the traveler has to be in the station between the hour and five after the hour The rest of the time, he will sit and wait for the A bus to arrive on the hour.

The problem of finding the next bus leaving the station is a fairly easy bit of SQL Here is a simple table for an imaginary bus line schedule It gives the route number and the departure and arrival times for one day, without regard to the departure or destination points:

CREATE TABLE Schedule(route_nbr INTEGER NOT NULL, depart_time TIMESTAMP NOT NULL, arrive_time TIMESTAMP NOT NULL, CHECK (depart_time < arrive_time), PRIMARY KEY (route_nbr, depart_time));

INSERT INTO Schedule VALUES (3, '2006-02-09 10:00', '2006-02-09 14:00'), (4, '2006-02-09 16:00', '2006-02-09 17:00'), (5, '2006-02-09 18:00', '2006-02-09 19:00'), (6, '2006-02-09 20:00', '2006-02-09 21:00'), (7, '2006-02-09 11:00', '2006-02-09 13:00'), (8, '2006-02-09 15:00', '2006-02-09 16:00'), (9, '2006-02-09 18:00', '2006-02-09 20:00');

If you want to catch the next bus at “2006-02-09 15:30,” you should return (route_nbr = 4) If the time is “2006-02-09 16:30,” then you should return route numbers 4 and 9, since both of them will depart at the same time.

Trang 20

Answer #1

Okay, how can we solve the problem? The computational way to do so is

to find the departure times that occur on or after the time you arrived at the station:

SELECT E1.event_id, E1.depart_time, E1.arrive_time FROM Events AS E1

WHERE E1.depart_time = (SELECT MIN(E2.depart_time) FROM Events AS E2

WHERE :my_time <= E2.depart_time);

This will work fine because the primary key should give you fast access to the departure time column for computing the MIN().

CREATE TABLE Schedule(route_nbr INTEGER NOT NULL, wait_time TIMESTAMP NOT NULL, depart_time TIMESTAMP NOT NULL, arrive_time TIMESTAMP NOT NULL, CHECK (depart_time < arrive_time), PRIMARY KEY (route_nbr, depart_time));

Now the table looks like this:

INSERT INTO Schedule VALUES (3, '2006-02-09 00:00', '2006-02-09 10:00', '2006-02-09 14:00'),

(7, 09 10:00', 09 11:00',

'2006-02-09 13:00'),

Ngày đăng: 26/01/2014, 08:20

TỪ KHÓA LIÊN QUAN

w