My problem
I am actually developing an SQLite database for an android application. I come from MySQL, where the query I'll expose works nicely.
This is my database structure:
table1: mid int(1) primary key autoincrement, name varchar(256)
table2: aid int(1) primary key autoincrement, name varchar(256)
With data inserted:
table1, row1: 1, "abc"
table2, row1: 1, "def"
What I want to do
I want to do a union so that the resulting data is:
| mid | aid | name |
--------------------
| 1 | 0 |"abc" |
| 0 | 1 |"def" |
So, I came up with this simple query:
select mid, name, 0 as aid from table1 union select aid, name, 0 as mid from table2;
However, I'm getting this back:
| mid | name | aid |
--------------------
| 1 |"abc" | 0 |
| 1 |"def" | 0 |
(I don't mind the column order)
This is of course not what I am looking for, and I can't see what I am doing wrong.
Any help will be appreciatted.
Thank you.
Maybe it's the column order that's tripping it up?
How about
select mid, 0 as aid, name from table1 union select 0 as mid, aid, name from table2;
works for me, at least on SQLFiddle: http://sqlfiddle.com/#!2/157f09/1
Related
I'm having a difficult time understanding why does the same query on the same database is correct on my local testing environment (my computer) and is wrong over my device/emulator.
The database is literally the same (copied from emulator to computer).
SELECT * FROM (
SELECT name, max(date_col) as date_col, value FROM tbl
WHERE date_col <= '2021-06-30'
GROUP BY name
UNION
SELECT name, min(date_col) as date_col, value FROM tbl
GROUP BY name
ORDER BY date_col DESC
)
GROUP BY name
The schema for the table is (id, date_col, name, value).
What I'm trying to do is select all the rows with the nearest date to the supplied date. I'm not quite sure that this is the best way of doing it so any suggestions are welcomed
When trying this query in my computer (SQLITE v3.27.2) it works as intended and when testing on a device/emulator (Tried multiple API levels such as 23, 27, 28) they all failed.
Edit:
Table data:
|name |date_col |value|
|-----|----------|-----|
|NAME6|2021-06-29|71 |
|NAME7|2021-06-29|80 |
|NAME1|2021-06-29|2925 |
|NAME4|2021-06-29|182.0|
|NAME2|2021-06-29|365 |
|NAME3|2021-06-29|81.0 |
|NAME5|2021-06-29|0.25 |
|NAME7|2021-06-27|81.0 |
|NAME1|2021-06-27|3000 |
|NAME5|2021-06-01|0.35 |
|NAME6|2021-06-01|68.0 |
|NAME5|2021-06-28|0.15 |
Results on device (for date 2021-06-28):
|name |date_col |value|
|-----|----------|-----|
|NAME1|2021-06-27|3000 |
|NAME2|2021-06-29|365.0|
|NAME3|2021-06-29|81.0 |
|NAME4|2021-06-29|182.0|
|NAME5|2021-06-01|0.35 |
|NAME6|2021-06-01|68.0 |
|NAME7|2021-06-27|81.0 |
Results on computer (for date 2021-06-28):
|name |date_col |value|
|-----|----------|-----|
|NAME1|2021-06-27|3000 |
|NAME2|2021-06-29|365.0|
|NAME3|2021-06-29|81.0 |
|NAME4|2021-06-29|182.0|
|NAME5|2021-06-28|0.15 |
|NAME6|2021-06-01|68.0 |
|NAME7|2021-06-27|81.0 |
As you can see, in this example the difference is with name5, it should be 0.15 but on device for some reason its 0.35.
What could be the reason for these differences?
Thank you very much!
SQLite allows statements with SELECT * and GROUP BY, but the resulting rows are arbitrary.
If you want to use this in lower API levels, you can't use window functions which would easily solve the problem like this:
SELECT name, date_col, value
FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY name
ORDER BY date_col < '2021-06-28' DESC,
abs(strftime('%s', date_col) - strftime('%s', '2021-06-28'))
) rn
FROM tbl
)
WHERE rn = 1
ORDER BY name;
You can use a correlated subquery:
SELECT t1.name, t1.date_col, t1.value
FROM tbl t1
WHERE t1.date_col = (
SELECT t2.date_col
FROM tbl t2
WHERE t2.name = t1.name
ORDER BY date_col < '2021-06-28' DESC,
abs(strftime('%s', t2.date_col) - strftime('%s', '2021-06-28'))
LIMIT 1
)
ORDER BY name;
See the demo.
I need to find an alternative to LAG and LEAD for finding the previous and next entry in my table in SQLite since those are not support in the version used (updating is not an option).
But I also cant use the value I order by, since it can be a date and therefore can be identical on multiple entries.
Since the table has to be sorted by date, using the ID isn't an option either.
It'd be great if someone knew an alternative way of dealing with this issue, since after more than an hour of searching and trying I am out of ideas.
Edit:
The important columns to my use case are:
_id booking_date
1 2017:11-21
3 2017:11-21
4 2017:11-21
5 2017:11-21
2 2017:11-22
6 2017:11-22
7 2017:11-22
...
_id is the primary key.
The bookings need to be sorted by date.
It is possible for multiple bookings to have the same date.
Bookings with the same date are sorted by their ids (See id 2, 6 and 7 in the give n example)
I need a way to query the entry before and after an entry by its id.
For example for _id=6 the I need a query that selects the row with _id=2 and a query that selects the row with _id=7.
Alternatively a query single query that selects both will work just as good.
I do not need you to provide an entire query, but rather an approach to this issue.
Try something like that, this retrieves previous and next id of a given record using your sort order (by date+id) - assumming that id is the primary key, you can retrieve other columns od prev-next records using these ids:
SELECT *,
(SELECT id FROM t t1
WHERE t1.booking_date < t.booking_date
OR t1.booking_date = t.booking_date AND t1.id < t.id
ORDER BY booking_date DESC, ID DESC LIMIT 1 ) prev_id,
(SELECT id FROM t t1
WHERE t1.booking_date > t.booking_date
OR t1.booking_date = t.booking_date AND t1.id > t.id
ORDER BY booking_date , ID LIMIT 1 ) next_id
FROM t
order by booking_date, id
Demo: http://www.sqlfiddle.com/#!5/17631/2
| id | booking_date | prev_id | next_id |
|----|--------------|---------|---------|
| 1 | 2017-11-21 | (null) | 3 |
| 3 | 2017-11-21 | 1 | 4 |
| 4 | 2017-11-21 | 3 | 5 |
| 5 | 2017-11-21 | 4 | 2 |
| 2 | 2017-11-22 | 5 | 6 |
| 6 | 2017-11-22 | 2 | 7 |
| 7 | 2017-11-22 | 6 | (null) |
If the table looked like this, the final select would be fairly trivial.
_id booking_date seq
1 2017:11-21 1
3 2017:11-21 2
4 2017:11-21 3
5 2017:11-21 4
2 2017:11-22 1
6 2017:11-22 2
7 2017:11-22 3
seq being the number of rows in the same booking_date with smaller id. You could create a virtual view with this structure to drive the main select.
This is a possible approach. Since you were not soliciting "an entire query", I leave it up to you how to implement this idea.
I'm using SQLite in Android
I have a table so.
idrow---message---date------transmitter----id_name
1 | Hello | 13-09-14 | Mike | 307
2 | Thanks | 17-09-14 | Louis | 12
3 | Byebye | 18-09-14 | Charlie | 879
4 | Hello | 18-09-14 | Mike | 307
5 | bllaaa | 18-09-14 | Mike | 307
6 | Nice | 19-09-14 | Charlie | 879
7 | Great | 19-09-14 | Mike | 307
I want to get the last inserted row for each id_name .
For example:
Of id_name 307: 7 | Great | 19-09-14 | Mike |
Of id_name 879 6 | Nice | 19-09-14 | Charlie |
Of Louis 12 2 | Thanks | 17-09-14 | Louis |
I try to use this but does not work as expected
String Query = "Select * from TableName, max(id_row) group by id_name" ;
Your query works only in SQLite 3.7.11 or later, which you will not have before API level 16 (Jelly Bean).
In earlier versions, non-grouped columns are not guaranteed to come from the row that matches the MAX().
You have to look up the maximum ID for each id_name separately, either with a join:
SELECT TableName.*
FROM TableName
JOIN (SELECT MAX(id_row) AS id_row
FROM TableName
GROUP BY id_name
) USING (id_row)
or with IN:
SELECT *
FROM TableName
WHERE id_row IN (SELECT MAX(id_row)
FROM TableName
GROUP BY id_name)
(Both queries work the same.)
Well,you can use the following code too...
SELECT * FROM TableName ORDER BY idrow DESC LIMIT 1
and may be you are getting error because of using id_row instead of idrow
Try This
select * from TableName
where id_row = (SELECT max(id_row) FROM TableName)
order by id_row desc
limit 1
I'm trying to realize a query but I don't know how to built it.
My tabs is something like this:
date, type_fruit, price
and records are something like this:
date_1, orange, 10$
date_1, orange, 5$
date_2, peach, 3$
date_3, banana, 25$
date_3, apple, 10$
My goal is build a tab like this:
| ---------------------------------------
| | orange | banana | apple |
| date_1 | 15$ | 0$ | 0$ |
| date_3 | 0$ | 25$ | 10$ |
|----------------------------------------
but...but...taking just top 3 bought fruits!
So, taking from SQLite DB just orange (10$+5$), banana (25$) and apple(10$) and not taking peach (only 3$).
Could anyone help me please?
PS: I hope I explained my problem in a clear way, sorry for some english mistake.
This is example for SQL SERVER.
IF you use another DB maybe will be chages.
if OBJECT_ID('tempdb..#example') IS NOT NULL
drop table #example
go
create table #example
(
[date] date,
type_fruit varchar(100),
price int
)
insert into #example
select
getdate() as [date], 'orange' as type_fruit, 10 as price
union select
getdate(), 'orange', 5
union select
getdate()-1, 'peach', 3
union select
getdate()-2, 'banana', 25
union select
getdate()-2, 'apple', 10
SELECT [DATE], ISNULL(orange,0)orange, ISNULL(banana,0)orange,ISNULL(apple,0)orange
FROM (
SELECT [date], type_fruit, price
FROM #example) up
PIVOT (SUM(PRICE) FOR type_fruit IN ( orange, banana,apple)) AS pvt
WHERE isnull(orange,-1)+isnull(banana,-1)+ISNULL(apple,-1) <> -3
GO
I hope this is will hekp you.
I have to tables:
Table A
id | title
1 | toto
2 | tata
3 | titi
Table B
id | title_id | tag_id
1 | 1 | 6
2 | 1 | 16
3 | 1 | 26
4 | 2 | 6
5 | 2 | 7
6 | 2 | 16
7 | 3 | 2
8 | 3 | 1
9 | 3 | 16
(Sorry for the bad table display)
In my application I have a tag listview with checkboxes, and when the user clicks a checkbox, I want to filter the titles with the clicked checkboxes:
(E.g: if user clicks tag 16, I should have title 1, 2 and 3 displayed. But if user clicks tag with id 26 AND tag with id 16, as result I should have only title with id 1)
I thought to a query like that:
SELECT DISTINCT A.title , A.id
FROM A
INNER JOIN B
ON B.title_id = A.id
WHERE B.tag_id = 26 AND B.tag_id = 16;
but obviously the last part of the query (two AND clause on a same column) is wrong, and I do not find a query which will give me this result.
I tried this :
SELECT DISTINCT A.title , A.id
FROM A
INNER JOIN B
ON B.title_id = A.id
WHERE B.tag_id IN ( '26', '16');
but the IN clause is like a OR clause, and as result, I get all the rows for value 26 plus all the rows for value 16 (title 1, 2 and 3) and not ONLY title 1.
I absolutely need to do this with and sql query because I'm using a SimpleCursorAdapter in order retrieve the datas and to fill an other listview.
I searched for a while, but I didn't find any relevant solution. (Or maybe I typed the wrong words...)
Do you have solution for me please?
PS: I hope I've been clear. Sorry for my bad english.
Use subqueries:
SELECT DISTINCT A.title, A.id FROM A WHERE
A.id IN (SELECT DISTINCT B.title_id FROM B WHERE B.tag_id='16')
AND A.id IN (SELECT DISTINCT B.title_id FROM B WHERE B.tag_id='26')