我在使用Postgres的SQL中执行以下操作时遇到了麻烦。我的程序有一组有序的数字。在我的数据库中,我有一个表,它存储了包含额外数据的行中的所有数字。这些行也按顺序排列。
例如我需要找的是我的套装;
1,5,6,1,3
数据库有行
row1 4
row2 5
row3 1
row4 5
row5 6
row6 1
row7 3
row8 2
row9 7
在上面的示例中,很容易看到我的集合从第3行到第7行。在SQL中仍然这样做对我来说是一个谜。我正在阅读一些有关数据透视表的文章,我仍然希望有一种更简单的方法。
答案 0 :(得分:4)
两个数据集都需要包含标识订单的字段。
如果排序列是一组连续的连续数字,那么这是可能的,虽然我怀疑它很快。
Table 1 Table 2
id | value id | value
1 4 1 1
2 5 2 5
3 1 3 6
4 5 4 1
5 6 5 3
6 1
7 3
8 2
9 7
然后这个查询...
SELECT
*
FROM
table_1
INNER JOIN
(
SELECT
MIN(table_1.id) AS first_id,
MAX(table_1.id) AS last_id
FROM
table_1
INNER JOIN
table_2
ON table_1.value = table_2.value
GROUP BY
table_1.id - table_2.id
HAVING
COUNT(*) = (SELECT COUNT(*) FROM table_2)
)
AS matched_sets
ON matched_sets.first <= table_1.id
AND matched_sets.last >= table_1.id
答案 1 :(得分:2)
@Dems打败了我: recursive CTE是这里的方法。它适用于任何数字序列。我发布我的版本是因为:
测试设置:
CREATE TEMP TABLE t (id int, val int);
INSERT INTO t VALUES
(1,4),(2,5),(3,1)
,(4,5),(5,6),(6,1)
,(7,3),(8,2),(9,7);
呼叫:
WITH RECURSIVE x AS (
SELECT '{1,5,6,1,3}'::int[] AS a
), y AS (
SELECT t.id AS start_id
,1::int AS step
FROM x
JOIN t ON t.val = x.a[1]
UNION ALL
SELECT y.start_id
,y.step + 1 -- AS step -- next step
FROM y
JOIN t ON t.id = y.start_id + step -- next id
JOIN x ON t.val = x.a[1 + step] -- next value
)
SELECT y.start_id
FROM x
JOIN y ON y.step = array_length(x.a, 1) -- only where last steps was matched
结果:
3
适用于预定义数量的数组项,但对于小型数组更快。这种情况下有5个项目。与上面相同的测试设置。
WITH x AS (
SELECT '{1,5,6,1,3}'::int[] AS a
)
SELECT t1.id
FROM x, t t1
JOIN t t2 ON t2.id = t1.id + 1
JOIN t t3 ON t3.id = t1.id + 2
JOIN t t4 ON t4.id = t1.id + 3
JOIN t t5 ON t5.id = t1.id + 4
WHERE t1.val = x.a[1]
AND t2.val = x.a[2]
AND t3.val = x.a[3]
AND t4.val = x.a[4]
AND t5.val = x.a[5];
答案 2 :(得分:0)
怎么样......
Select instr(',' & Group_Concat(mNumber SEPARATOR ',') &',',@yourstring)
FROM Table
哎呀,我的SQL必须为Postgresql查找类似的函数......
Postgresql Version of Group_concat
所有这一切都是将多行组合成一个长字符串,然后执行“查找”以返回生成的长字符串中字符串的第一个位置。返回的数字将与row_number匹配。如果返回0,则表示字符串不在生成的字符串中。 (可能必须对','逗号空间保持谨慎。
答案 3 :(得分:0)
递归回答......
WITH
CTE AS
(
SELECT
id AS first_id,
id AS current_id,
1 AS sequence_id
FROM
main_table
WHERE
value = (SELECT value FROM search_table WHERE id = 1)
UNION ALL
SELECT
CTE.first_id,
main_table.id,
CTE.sequence_id + 1
FROM
CTE
INNER JOIN
main_table
ON main_table.id = CTE.current_id + 1
INNER JOIN
search_table
ON search_table.value = main_table.value
AND search_table.id = CTE.sequence_id + 1
)
SELECT
*
FROM
main_table
INNER JOIN
CTE
ON main_table.id >= CTE.first_id
AND main_table.id <= CTE.current_id
WHERE
CTE.sequence_id = (SELECT COUNT(*) FROM search_table)