如何在sqlite中从表中选择行对?

taor4pac  于 2023-02-09  发布在  SQLite
关注(0)|答案(2)|浏览(168)

我有下面的模式:

CREATE TABLE video_segments (
        video_id TEXT,
        segment_num INTEGER,
        data BLOB
    )

我想从表中选择100对行,每对包含来自同一视频的2个片段,并且没有2对来自同一视频。
什么是最好的查询?
我试着做:

WITH CTE AS (
  SELECT video_id
  FROM video_segments
  GROUP BY video_id
  HAVING COUNT(*) >= 2
)
SELECT *
FROM video_segments
WHERE video_id IN (
  SELECT video_id
  FROM CTE
  ORDER BY RANDOM()
  LIMIT 100
)
ORDER BY RANDOM()
LIMIT 200;

但是这不起作用,因为有时会有0行具有给定的视频ID,而有时会有多于2行具有视频ID。
采样数据:

video_id|segment_num|data|
foo      0            <bin>
foo      1            <bin>
foo      2            <bin>
foo      3            <bin>
bar      0            <bin>
bar      1            <bin>
baz      0            <bin>
baz      1            <bin>
baz      2            <bin>

假设我想选择3个随机配对,有效的结果可能是:

foo 0 <bin>
foo 2 <bin>
bar 0 <bin>
bar 1 <bin>
baz 0 <bin>
baz 2 <bin>

因为结果应该是随机的。每次的结果应该不同。

yizd12fk

yizd12fk1#

像这样的东西应该做:
The fiddle
1.假设vid〈= 10是所选择的视频,并且
1.我们希望为每个选定的VID选择2个SID。
1.分别为每个vid中的每个sid随机分配一个行号。
1.然后为每个视频选择前2个行号(ord〈3
注:第一个递归CTE项仅用于创建节段的测试数据。

WITH segments (sid, vid) AS (
        SELECT 0  , 1 UNION ALL
        SELECT sid+1, 1 + (sid+1)/10 FROM segments WHERE sid < 100
     )
   , cte1 AS (
        SELECT t.*, row_number() OVER (PARTITION BY vid ORDER BY random()) AS ord
          FROM segments AS t
         WHERE vid <= 10
     )
SELECT * FROM cte1
 WHERE ord < 3
 ORDER BY vid, ord
;

现在将其应用到您的模式和初始逻辑中,我们得到如下结果:
The updated fiddle

WITH cte AS (
      SELECT video_id
        FROM video_segments
       GROUP BY video_id
      HAVING COUNT(*) >= 2
     )
   , cte1 AS (
      SELECT *, row_number() OVER (PARTITION BY video_id ORDER BY random()) AS ord
        FROM video_segments
       WHERE video_id IN (
                SELECT video_id
                  FROM cte
                 ORDER BY RANDOM()
                 LIMIT 100
             )
     )
SELECT * FROM cte1
 WHERE ord < 3
 ORDER BY video_id, ord
;

Fiddle updated with the new data
结果1:
| 视频_id|段_编号|资料|订单|
| - ------|- ------|- ------|- ------|
| 棒|1个|零|1个|
| 棒|无|零|第二章|
| 巴兹|无|零|1个|
| 巴兹|第二章|零|第二章|
| 富|1个|零|1个|
| 富|无|零|第二章|
结果二:
| 视频_id|段_编号|资料|订单|
| - ------|- ------|- ------|- ------|
| 棒|1个|零|1个|
| 棒|无|零|第二章|
| 巴兹|1个|零|1个|
| 巴兹|无|零|第二章|
| 富|第二章|零|1个|
| 富|三个|零|第二章|
等等。
在第一个小提琴测试用例中生成的更大的数据集显示了更好的随机行为。

cwdobuhd

cwdobuhd2#

使用随机排序的窗函数ROW_NUMBER()

WITH cte AS (
  SELECT *, 
         ROW_NUMBER() OVER (PARTITION BY video_id ORDER BY RANDOM()) rn,
         COUNT(*) OVER (PARTITION BY video_id) cnt
  FROM video_segments
)  
SELECT video_id, segment_num, data  
FROM cte
WHERE cnt >= 2 AND rn <= 2
ORDER BY video_id;

请参见demo

相关问题