一个用postgresql的自定义函数求解数独的程序

从这个网页看到一个用postgresql的自定义函数求解数独的程序,其实核心还是一个利用递归CTE的SQL。

然后把两个计算行列宫的临时表做成物理表。

对问题表中的每行执行上述标量函数,效率和单独的SQL差不多。难题耗时比较长。

复制代码
postgres@b3490d8427cd:~$ psql
psql (17.7 (Debian 17.7-3.pgdg13+1))
Type "help" for help.

postgres=# table sudoku9_9;
postgres=# CREATE TABLE allnum AS
SELECT generate_series(1, 9) AS num
;
SELECT 9
postgres=# CREATE TABLE grid AS
SELECT
         (i - 1) * 9 + j AS indexof
        ,i
        ,j
        ,(i - 1) / 3 * 3 + 1 + (j - 1) / 3 AS grp
FROM
         allnum n1(i)
        ,allnum n2(j)
;
SELECT 81
postgres=# CREATE OR REPLACE FUNCTION sudoku(text)
RETURNS text LANGUAGE sql IMMUTABLE AS $$
WITH RECURSIVE _sudoku AS (
-- 初期値
SELECT $1 kekka
-- 再帰with句で追加されていく行
UNION ALL(
	WITH latest AS (
		SELECT
			 kekka
			,(ROW_NUMBER() OVER())::int parallelid
		FROM _sudoku
	)
	,gridnum AS (
		SELECT
			 latest.parallelid
			,indexof, i, j, grp
			,substr(latest.kekka, indexof, 1) AS num
		FROM latest, grid
	)
	,used AS (
		SELECT
			 gridnums.parallelid
			,gridnums.indexof
			,array_agg(DISTINCT usednums.num :: int) usednumarray
		FROM
			 gridnum usednums
			,gridnum gridnums
		WHERE
			usednums.num <> ' '
			AND
			gridnums.num = ' '
			AND
			usednums.parallelid = gridnums.parallelid
			AND(
				usednums.i = gridnums.i
				OR
				usednums.j = gridnums.j
				OR
				usednums.grp = gridnums.grp
			)
		GROUP BY
			 gridnums.parallelid
			,gridnums.indexof
	)
	,insertnum AS (
		SELECT
			 parallelid
			,indexof
			,usednumarray
			,DENSE_RANK() OVER(
				PARTITION BY used.parallelid
				ORDER BY ARRAY_LENGTH(used.usednumarray, 1) DESC, indexof
			) AS insertorder
		FROM used
	)
	SELECT
		overlay(latest.kekka placing allnum.num::text FROM insertnum.indexof FOR 1) AS kekka
	FROM
		 latest
		,allnum
		,insertnum
	WHERE
		latest.parallelid = insertnum.parallelid
		AND
		insertnum.insertorder = 1
		AND
		allnum.num <> ALL(insertnum.usednumarray)
)
)
SELECT kekka
FROM _sudoku
WHERE strpos(kekka, ' ') = 0;
$$ ;
CREATE FUNCTION
postgres=# CREATE TABLE sudoku_q AS
      SELECT 1 id, '      6   3     1 9    5   2  31    14 678   786529 34567 93  1891456372 24 875 9'::text as question
UNION SELECT 2,    '     7  3      6 9152      23 48   7418  65  7 9325   876 9341 9215  37 5   18296'
UNION SELECT 3,    '   3   1967   4      8   2 34157 2    62315      68 9 13 68 9 258479 6  2 9143857'
UNION SELECT 4,    '   9  8   7  42   6     3    7 1 2  5   836 992  651 475 63491831 8 7452  9521 63'
UNION SELECT 5,    '  5           3  6 824  7 1 2954167 1 86 2954 6 7 9312  39784   563241 7 9   5283'
;
SELECT 5
postgres=# SELECT * FROM sudoku_q ORDER BY id;
 id |                                     question
----+-----------------------------------------------------------------------------------
  1 |       6   3     1 9    5   2  31    14 678   786529 34567 93  1891456372 24 875 9
  2 |      7  3      6 9152      23 48   7418  65  7 9325   876 9341 9215  37 5   18296
  3 |    3   1967   4      8   2 34157 2    62315      68 9 13 68 9 258479 6  2 9143857
  4 |    9  8   7  42   6     3    7 1 2  5   836 992  651 475 63491831 8 7452  9521 63
  5 |   5           3  6 824  7 1 2954167 1 86 2954 6 7 9312  39784   563241 7 9   5283
(5 rows)

postgres=# \timing
Timing is on.
postgres=# SELECT id, sudoku(question) FROM sudoku_q ORDER BY id;
 id |                                      sudoku
----+-----------------------------------------------------------------------------------
  1 | 472931658635842917918765423259314786143678295786529134567293841891456372324187569
  2 | 694857123387142659152639784235481967418976532769325841876293415921564378543718296
  3 | 458326719672914385913857426341579268896231574725468193137685942584792631269143857
  4 | 235976841178342596694158327867419235541283679923765184752634918316897452489521763
  5 | 635217849741893526982456731329541678178632954564789312213978465856324197497165283
(5 rows)

Time: 35.973 ms
postgres=# insert into sudoku_q SELECT 8 AS id, E'8          36      7  9 2   5   7       457     1   3   1    68  85   1  9    4  ';
INSERT 0 1
Time: 3.909 ms
postgres=# SELECT id, sudoku(question) FROM sudoku_q ORDER BY id;
 id |                                      sudoku
----+-----------------------------------------------------------------------------------
  1 | 472931658635842917918765423259314786143678295786529134567293841891456372324187569
  2 | 694857123387142659152639784235481967418976532769325841876293415921564378543718296
  3 | 458326719672914385913857426341579268896231574725468193137685942584792631269143857
  4 | 235976841178342596694158327867419235541283679923765184752634918316897452489521763
  5 | 635217849741893526982456731329541678178632954564789312213978465856324197497165283
  8 | 812753649943682175675491283154237896369845721287169534521974368438526917796318452
(6 rows)

Time: 4808.878 ms (00:04.809)
postgres=#
相关推荐
IvorySQL2 小时前
改变工作方式的 PostgreSQL 实用模式
数据库·postgresql
Anarkh_Lee2 小时前
在VSCode中使用MCP实现智能问数
数据库·ide·vscode·ai·编辑器·ai编程·数据库开发
晓13132 小时前
第八章:Redis底层原理深度详细解析
数据库·redis·缓存
电商API&Tina2 小时前
电商数据采集 API 接口 全维度解析(技术 + 商业 + 合规)
java·大数据·开发语言·数据库·人工智能·json
liwulin05062 小时前
【JSON】使用com.fasterxml.jackson解析json字符串
java·数据库·json
志凌海纳SmartX3 小时前
金融行业IT基础设施转型实践|450+机构部署轻量云,支持核心生产与信创业务
大数据·数据库·金融
VIP_CQCRE3 小时前
hCaptcha 验证码图像识别 API 对接教程
数据库
Mr_Xuhhh3 小时前
MySQL索引深度解析:从原理到实践
数据库·sql·mysql
爱学习的阿磊3 小时前
Python入门:从零到一的第一个程序
jvm·数据库·python