0

My table has 4 columns:

This is my database.

ID      SSID      BSSID         RSSI
1.      jbhd      ed:2d:5c      -60 
2.      ABCD      ab:cd:17      -68
3.      ijkl      cs:gb:d6      -75 
4.      vxfs      dc:5g:f4      -72
5.      cxzv      fg:4d:ac      -54
6.      ABCD      ab:cd:17      -68
7.      ertd      bv:we:12      -57
8.      erbc      gd:56:lt      -83

....
518.    ABCD      ab:cd:17      -68
519.    asfd      ag:4g:32      -60
520.    aasd      gd:5g:56      -79

I'm trying to write a function which query the database to return a specific record and 2 next records with highest ID.

What I've done so far is:

public Cursor get3records(String mac, int level){
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor res = db.rawQuery("SELECT * from Scans_table st where ID >= ( select ID from Scans_table where BSSID =? AND RSSI =? ) order by st.ID asc limit 3 ", new String[] {mac, String.valueOf(level)});
    return res;
}

mac and level are parameters that decide which records I want to get from the query.

For instance, take a look at the sample data provided. I want to get all records that have ab:cd:17 in BSSID column and -68 in RSSI column (records 2, 6, 518), and 2 next records with the highest ID (records 3, 4, 7, 8, 519, 520).

The problem is, this function returns result like this:

ID      SSID      BSSID         RSSI
2.      ABCD      ab:cd:17      -68
3.      ijkl      cs:gb:d6      -75 
4.      vxfs      dc:5g:f4      -72

Whereas the result I'm looking for should be like this:

ID      SSID      BSSID         RSSI
2.      ABCD      ab:cd:17      -68
3.      ijkl      cs:gb:d6      -75 
4.      vxfs      dc:5g:f4      -72
6.      ABCD      ab:cd:17      -68
7.      ertd      bv:we:12      -57
8.      erbc      gd:56:lt      -83
518.    ABCD      ab:cd:17      -68
519.    asfd      ag:4g:32      -60
520.    aasd      gd:5g:56      -79
4

3 回答 3

0
select * from tablename where id in(
select id from tablename where BSSID=? and RSSI=?,
(select id from tablename where BSSID=? and RSSI=?)+1,
(select id from tablename where BSSID=? and RSSI=?)+2) 
于 2018-12-16T14:28:25.863 回答
0

我没有要提出的 sql 语句,而是获得所需结果的 java 方法。它首先获取满足条件的 id:

where BSSID =? AND RSSI =?

然后对于这些 id 中的每一个,它会获取以下 2 个 id。
它将所有获取的 id 包装在一条IN语句中并执行最后一条SELECT语句:

public Cursor get3records(String mac, int level){
    SQLiteDatabase db = this.getReadableDatabase();

    Cursor res = db.rawQuery("SELECT * from Scans_table st where BSSID = ? AND RSSI = ?", new String[] {mac, String.valueOf(level)});

    List<Integer> list = new ArrayList<>();

    if (res.moveToFirst()) {
        do {
            list.add(res.getInt(0));
        } while (res.moveToNext());
    }

    res.close();

    if (list.size() == 0)
        return null;

    List<Integer> all = new ArrayList<>(list);

    for (int id : list) {
        res  = db.rawQuery("SELECT id from Scans_table where id > ? ORDER BY id LIMIT 2", new String[] {String.valueOf(id)});

        if (res.moveToFirst()) {
            do {
                all.add(res.getInt(0));
            } while (res.moveToNext());
        }

        res.close();
    }

    StringBuilder sb = new StringBuilder("");
    for (int id : all) {
        sb.append(String.valueOf(id)).append(",");
    }
    String sqlIn = sb.toString();
    sqlIn = sqlIn.substring(0, sqlIn.length() - 1);

    return db.rawQuery("SELECT * from Scans_table where id IN (" + sqlIn + ") ORDER BY id", null);
}

如果有一条 sql 语句可以产生你想要的结果,也许它会更有效或更快。
如果你没有找到,那么 java 可以是解决方案。
PS 我希望我没有错别字...

于 2018-12-16T14:55:37.660 回答
0

如果ids 是连续的,没有间隙(如您的示例中所示),您可以执行以下操作:

select st.*
from scans_table st join
     (select st2.id
      from scans_table st2
      where bssid = ? and rssi = ?
     ) ids
     on st.id in (ids.id, ids.id + 1, ids.id + 2);

如果 id 不是连续的,这将变得更加棘手。最简单的方法可能是实现一个lag()

select *
from (select st.*,
             (select st2.bssid
              from scans_table st2
              where st2.id < st.id
              order by st2.id desc
              limit 1
             ) as prev_bssid,
             (select st2.rssi
              from scans_table st2
              where st2.id < st.id
              order by st2.id desc
              limit 1
             ) as prev_rssi,
             (select st2.bssid
              from scans_table st2
              where st2.id < st.id
              order by st2.id desc
              limit 1, 1
             ) as prev2_bssid,
             (select st2.rssi
              from scans_table st2
              where st2.id < st.id
              order by st2.id desc
              limit 1, 1
             ) as prev2_rssi
      from scans_table st
     ) st
where (bssid = ? and rssi = ?) or
      (prev_bssid = ? and prev_rssi = ?) or
      (prev2_bssid = ? and prev2_rssi = ?);

当然,如果您使用的是最新版本的 SQLite,您可以使用窗口函数,这会更容易:

select *
from (select st.*,
             lag(bssid) over (order by id) as prev_bssid,
             lag(rssi) over (order by id) as prev_rssid,
             lag(bssid, 2) over (order by id) as prev2_bssid,
             lag(rssi, 2) over (order by id) as prev2_rssid
      from scans_table st
     ) st
where (bssid = ? and rssi = ?) or
      (prev_bssid = ? and prev_rssi = ?) or
      (prev2_bssid = ? and prev2_rssi = ?);
于 2018-12-16T14:24:59.057 回答