如何使用单个查询按位置获取多行?

问题描述 投票:1回答:6

我可以通过偏移和限制的位置获得单行。但我有一系列的职位,我想从这些职位获得行数。

有没有办法在没有for循环的情况下通过单个查询获取这些行?

注意:id不为我所知。我的案件位置不是ids。

为什么我需要这个:

SELECT question_id FROM questions where question_bank_id in (1, 3) ORDER BY RANDOM() LIMIT 5

上面的查询从1和3返回5个随机值。但我需要5行,从1行和5行5.我可以通过循环实现这一点。但是我的桌子很大。

所以我找到了一种有效实现这一目标的替代方案。这就是为什么我想先生成随机整数然后从那些位置获取值。

android sqlite
6个回答
2
投票

要获得单行,您将使用如下查询:

SELECT ... FROM ... ORDER BY ... LIMIT 1 OFFSET ?;

要获取多行,请合并多个查询:

SELECT ... FROM ... ORDER BY ... LIMIT 1 OFFSET ?
UNION ALL
SELECT ... FROM ... ORDER BY ... LIMIT 1 OFFSET ?
UNION ALL
SELECT ... FROM ... ORDER BY ... LIMIT 1 OFFSET ?
...

您需要一个for循环来构造此查询,因此执行多个查询可能会更容易。


1
投票

注意:这个答案是根据原始问题引用的mySQL

我不知道它是否适合您作为单个查询,但它可能会尽可能接近您:

SET @row_num = 0;

SELECT
    *
FROM
    (
        SELECT 
            @row_num := @row_num + 1 AS row_number, 
            t.id
       FROM 
           your_table AS t 
       ORDER BY 
           t.id) AS q
WHERE
    q.row_number IN (3, 5);

我假设你想通过它的订单来定位而不是唯一的id键。上面的查询创建临时row_number,可用于选择任意数量的位置。

请注意,行选择将取决于ORDER BY中的字段 - 它不必是id(主键)。


1
投票

我没试过(见下文)这个,但你也许可以使用MergeCursor。

这是为所需的银行创建一个游标数组,然后使用它们创建一个MergeCursor,然后使用它。

沿着: -

String sqlbank1 = 
    "SELECT question_id FROM questions WHERE question_bank_id = 1 ORDER BY random() LIMIT 5";
String sqlbank2 = 
    "SELECT question_id FROM questions WHERE question_bank_id = 3 ORDER BY random() LIMIT 5";
Cursor[] cursors = new Cursor[]{db.rawQuery(sqlbank1),db.rawQuery(sqlbank2)};
Cursor questions = new MergeCursor(cursors);
// or MergeCursor questions = new MergCursor(cursors); 

注意!未经测试,因此代码原则上是。您还应该关闭游标(我没有尝试过,因此不确定关闭数组中的游标是否会影响MergeCursor,最好假设这样,并在完成后关闭所有游标)。

MergeCursor


工作实例: -

调用活动MainActivity.java: -

public class MainActivity extends AppCompatActivity {

    DatabaseHelper dbhlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dbhlpr = new DatabaseHelper(this);
        dbhlpr.populateQuestions(500,6);
        Cursor questions = dbhlpr.getRandomQuestionsForBanks(new int[]{1,3},5);

        while (questions.moveToNext()) {
            Log.d("QUESTIONS",
                    "ID=" +   questions.getLong(questions.getColumnIndex(DatabaseHelper.QUESTION_ID_COL)) +
                    " BANK=" + questions.getInt(questions.getColumnIndex(DatabaseHelper.QUESTION_BANK_ID))+
                    " QUESTION=" + questions.getString(questions.getColumnIndex(DatabaseHelper.QUESTION_QUESTION))
            );
        }
        questions.close();
    }
}

数据库助手Databasehelper.java

public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "questionsdb";
    public static final int DBVERSION = 1;
    public static final String QUESTIONS_TBNAME = "questions";
    public static final String QUESTION_ID_COL = "question_id";
    public static final String QUESTION_BANK_ID = "question_bank_id";
    public static final String QUESTION_QUESTION = "question_question";

    SQLiteDatabase mDB;
    static Random r;

    DatabaseHelper(Context context) {
        super(context, DBNAME,null,DBVERSION);
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String questions_crtsql = "CREATE TABLE IF NOt EXISTS " + QUESTIONS_TBNAME +
                "(" +
                QUESTION_ID_COL + " INTEGER PRIMARY KEY," +
                QUESTION_BANK_ID + " INTEGER, " +
                QUESTION_QUESTION + " TEXT" +
                ")";
        db.execSQL(questions_crtsql);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public void populateQuestions(int rowstoadd, int numberofbanks) {
        final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        Random r = new Random(System.currentTimeMillis());
        ContentValues cv = new ContentValues();
        if (DatabaseUtils.queryNumEntries(mDB,QUESTIONS_TBNAME) < 1) {
            mDB.beginTransaction();
            for (int i = 0; i < rowstoadd; i++) {
                int aix = r.nextInt(alphabet.length());
                int bank = r.nextInt(numberofbanks) + 1;
                cv.clear();
                cv.put(QUESTION_BANK_ID,bank);
                cv.put(QUESTION_QUESTION,alphabet.substring(aix,aix+1));

                mDB.insert(QUESTIONS_TBNAME,null,cv);
            }
            mDB.setTransactionSuccessful();
            mDB.endTransaction();
            Log.d("POPULATE","Number of rows in table after populate is" + DatabaseUtils.queryNumEntries(mDB,QUESTIONS_TBNAME));
        } else {
            Log.d("POPULATE","Number of rows in table is" + DatabaseUtils.queryNumEntries(mDB,QUESTIONS_TBNAME));
        }
    }

    public Cursor getRandomQuestionsPerBank(int bank, int numbertoget) {
        return  mDB.query(
                QUESTIONS_TBNAME,
                new String[]{QUESTION_ID_COL, QUESTION_QUESTION, QUESTION_BANK_ID},
                QUESTION_BANK_ID + "=?",
                new String[]{Integer.toString(bank)},
                null, null," random()",
                Integer.toString(numbertoget)
        );
    }

    public Cursor getRandomQuestionsForBanks(int[] banklist, int numbertoget) {
        Cursor[] cursors = new Cursor[banklist.length];
        for (int i=0; i < banklist.length; i++) {
            cursors[i] = getRandomQuestionsPerBank(banklist[i],numbertoget);
        }
        return new MergeCursor(cursors);
    }
}

示例3次运行的输出为: -

12-27 07:19:22.747 2370-2370/? D/POPULATE: Number of rows in table after populate is500
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=414 BANK=1 QUESTION=I
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=215 BANK=1 QUESTION=P
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=336 BANK=1 QUESTION=L
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=243 BANK=1 QUESTION=M
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=226 BANK=1 QUESTION=H
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=376 BANK=3 QUESTION=Y
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=282 BANK=3 QUESTION=M
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=113 BANK=3 QUESTION=M
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=80 BANK=3 QUESTION=O
12-27 07:19:22.748 2370-2370/? D/QUESTIONS: ID=413 BANK=3 QUESTION=D

12-27 07:23:29.502 2561-2561/? D/POPULATE: Number of rows in table is500
12-27 07:23:29.503 2561-2561/? D/QUESTIONS: ID=226 BANK=1 QUESTION=H
12-27 07:23:29.503 2561-2561/? D/QUESTIONS: ID=414 BANK=1 QUESTION=I
12-27 07:23:29.503 2561-2561/? D/QUESTIONS: ID=124 BANK=1 QUESTION=A
12-27 07:23:29.503 2561-2561/? D/QUESTIONS: ID=128 BANK=1 QUESTION=I
12-27 07:23:29.503 2561-2561/? D/QUESTIONS: ID=379 BANK=1 QUESTION=U
12-27 07:23:29.503 2561-2561/? D/QUESTIONS: ID=282 BANK=3 QUESTION=M
12-27 07:23:29.504 2561-2561/? D/QUESTIONS: ID=275 BANK=3 QUESTION=Z
12-27 07:23:29.504 2561-2561/? D/QUESTIONS: ID=371 BANK=3 QUESTION=C
12-27 07:23:29.504 2561-2561/? D/QUESTIONS: ID=106 BANK=3 QUESTION=M
12-27 07:23:29.504 2561-2561/? D/QUESTIONS: ID=35 BANK=3 QUESTION=B

12-27 07:24:06.794 2621-2621/mjt.questionsmergecursor D/POPULATE: Number of rows in table is500
12-27 07:24:06.795 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=292 BANK=1 QUESTION=B
12-27 07:24:06.795 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=201 BANK=1 QUESTION=F
12-27 07:24:06.795 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=384 BANK=1 QUESTION=I
12-27 07:24:06.795 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=305 BANK=1 QUESTION=M
12-27 07:24:06.796 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=50 BANK=1 QUESTION=S
12-27 07:24:06.796 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=295 BANK=3 QUESTION=U
12-27 07:24:06.796 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=66 BANK=3 QUESTION=Z
12-27 07:24:06.796 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=290 BANK=3 QUESTION=F
12-27 07:24:06.796 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=91 BANK=3 QUESTION=O
12-27 07:24:06.796 2621-2621/mjt.questionsmergecursor D/QUESTIONS: ID=433 BANK=3 QUESTION=S

注意!我测试关闭阵列游标,你不能得到java.lang.IllegalStateException: attempt to re-open an already-closed object。所以代码应该有助于关闭数组游标。


-2
投票

你可以使用IN。像SELECT * FROM table_name WHERE ID IN (1,2,3,4,5);


-2
投票

使用像这样的SQL语句:

SELECT column_name(s)FROM table_name WHERE position IN(1,2,...);


-2
投票

方式1:

您可以使用以下查询来实现此目的:

Select * from your_table_name where rowid in (1,5,6,10,15);

在这里,在括号(1,5,6,10,15)中,您将从您的阵列数组中传递位置。

方式2 :(优先用于少量数据)

如果方式1不符合您的要求,则将此表中的所有记录提取到一个列表中,并从此列表中获取所需位置的项目。

© www.soinside.com 2019 - 2024. All rights reserved.