SQLite find table row where a subset of columns satisfies a specified constraint - sqlite

I have the following SQLite table
CREATE TABLE visits(urid INTEGER PRIMARY KEY AUTOINCREMENT,
hash TEXT,dX INTEGER,dY INTEGER,dZ INTEGER);
Typical content would be
# select * from visits;
urid | hash | dx | dY | dZ
------+-----------+-------+--------+------
1 | 'abcd' | 10 | 10 | 10
2 | 'abcd' | 11 | 11 | 11
3 | 'bcde' | 7 | 7 | 7
4 | 'abcd' | 13 | 13 | 13
5 | 'defg' | 20 | 21 | 17
What I need to do here is identify the urid for the table row which satisfies the constraint
hash = 'abcd' AND (nearby >= (abs(dX - tX) + abs(dY - tY) + abs(dZ - tZ))
with the smallest deviation - in the sense of smallest sum of absolute distances
In the present instance with
nearby = 7
tX = tY = tZ = 12
there are three rows that meet the above constraint but with different deviations
urid | hash | dx | dY | dZ | deviation
------+-----------+-------+--------+--------+---------------
1 | 'abcd' | 10 | 10 | 10 | 6
2 | 'abcd' | 11 | 11 | 11 | 3
4 | 'abcd' | 12 | 12 | 12 | 3
in which case I would like to have reported urid = 2 or urid = 3 - I don't actually care which one gets reported.
Left to my own devices I would fetch the full set of matching rows and then dril down to the one that matches my secondary constraint - smallest deviation - in my own Java code. However, I suspect that is not necessary and it can be done in SQL alone. My knowledge of SQL is sadly too limited here. I hope that someone here can put me on the right path.
I now have managed to do the following
CREATE TEMP TABLE h1(v1 INTEGER,v2 INTEGER);
SELECT urid,(SELECT (abs(dX - 12) + abs(dY - 12) + abs(dZ - 12))) devi FROM visits WHERE hash = 'abcd';
which gives
--SELECT * FROM h1
urid | devi |
-------+-----------+
1 | 6 |
2 | 3 |
4 | 3 |
following which I issue
select urid from h1 order by v2 asc limit 1;
which yields urid = 2, the result I am after. Whilst this works, I would like to know if there is a better/simpler way of doing this.

You're so close! You have all of the components you need, you just have to put them together into a single query.
Consider:
SELECT urid
, (abs(dx - :tx) + abs(dy - :tx) + abs(dz - :tx)) AS devi
FROM visits
WHERE hash=:hashval AND devi < :nearby
ORDER BY devi
LIMIT 1
Line by line, first you list the rows and computed values you want (:tx is a placeholder; in your code you want to prepare a statement and then bind values to the placeholders before executing the statement) from the visit table.
Then in the WHERE clause you restrict what rows get returned to those matching the particular hash (That column should have an index for best results... CREATE INDEX visits_idx_hash ON visits(hash) for example), and that have a devi that is less than the value of the :nearby placeholder. (I think devi < :nearby is clearer than :nearby >= devi).
Then you say that you want those results sorted in increasing order according to devi, and LIMIT the returned results to a single row because you don't care about any others (If there are no rows that meet the WHERE constraints, nothing is returned).

Related

SQLITE order by numeric and not alphabetic

When I order my database SQLITE by Classement I have this :
Classement | Nom
1 | clem
10 | caro
11 | flo
12 | raph
2 | prisc
3 | karim
4 | prout
I would like to get :
Classement | Nom
1 | clem
2 | prisc
3 | karim
4 | prout
10 | caro
11 | flo
12 | raph
Here is my code :
SELECT t.Classement
FROM tableau t
WHERE 1 = (SELECT 1 + COUNT (*) FROM tableau t2 WHERE t2.Classement < t.Classement OR ( t2.Classement == t.Classement AND t2.Nom < t.Nom ))
Can anyone help me ?
Thank you!
I guess column Classement is not an integer but character. So try this:
SELECT * FROM tableau ORDER BY cast(Classement as integer);
You get alphabetic order if the values are strings.
To change the table so that all Classement values are numbers, ensure that the column type is not a text type, and use this:
UPDATE tableau SET Classement = CAST(Classement AS NUMBER);

Levensthein logic to get all the string with minimum difference

Suppose i have a datframe with values
Mtemp:
-----+
code |
-----+
Ram |
John |
Tracy|
Aman |
i want to compare it with dataframe
M2:
------+
code |
------+
Vivek |
Girish|
Rum |
Rama |
Johny |
Stacy |
Jon |
i want to get result so that for each value in Mtemp i will get maximum 2 possible match in M2 with Levensthein distance 2.
i have used
tp<-as.data.frame(amatch(Mtemp$code,M2$code,method = "lv",maxDist = 2))
tp$orig<-Mtemp$code
colnames(tp)<-c('Res','orig')
and i am getting result as follow
Res |orig
-----+-----
3 |Ram
5 |John
6 |Tracy
4 |Aman
please let me know a way to get 2 values(if possible) for every Mtemp string with Lev distance =2

sqlite, order by date/integer in joined table

I have two tables
Names
id | name
---------
5 | bill
15 | bob
10 | nancy
Entries
id | name_id | added | description
----------------------------------
2 | 5 | 20140908 | i added this
4 | 5 | 20140910 | added later on
9 | 10 | 20140908 | i also added this
1 | 15 | 20140805 | added early on
6 | 5 | 20141015 | late to the party
I'd like to order Names by the first of the numerically-lowest added values in the Entries table, and display the rows from both tables ordered by the added column overall, so the results will be something like:
names.id | names.name | entries.added | entries.description
-----------------------------------------------------------
15 | bob | 20140805 | added early on
5 | bill | 20140908 | i added this
10 | nancy | 20140908 | i also added this
I looked into joins on the first item (e.g. SQL Server: How to Join to first row) but wasn't able to get it to work.
Any tips?
Give this query a try:
SELECT Names.id, Names.name, Entries.added, Entries.description
FROM Names
INNER JOIN Entries
ON Names.id = Entries.name_id
ORDER BY Entries.added
Add DESC if you want it in reverse order i.e.: ORDER BY Entries.added DESC.
This should do it:
SELECT n.id, n.name, e.added, e.description
FROM Names n INNER JOIN
(SELECT name_id, description, Min(added) FROM Entries GROUP BY name_id, description) e
ON n.id = e.name_id
ORDER BY e.added

sql server compare rows in one table

i want to keep track of the changes of a system setup and also to display them in a web application ASP.net VB.
the setup information/data is stored in a table like this:
TABLE 1
| SNR | LENSE | CAMERA | SYS |
|-----|-------|--------|-----|
| 1 | 55mm | rcd30 | 5 | (initial setup sys 5)
| 2 | 80mm | ph1 | 4 | (initial setup sys 4)
| 3 | 80mm | ph1 | 4 | (new setup sys 4)
| 4 | 55mm | ph1 | 5 | (new setup sys 5)
| 5 | 80mm | rcd30 | 5 | (new setup sys 5)
what i want is to compare for both systems (4 and 5) if and which changes occur between setups of the same system and to create a table where i keep the results and from here to display them every time i load the list of setups.
for example if i compare setup's for the sys nr 5, comparing row 1 and 4 there is a difference on camera; between 4 and 5 both the camera and the lense changes. this works if considering the first record for each system as the initial setup.
CHANGES
| SNR | LENSE | CAMERA | SYS |
|-----|-------|--------|-----|
| 1 | n | n | 5 | (initial setup sys 5)
| 2 | n | n | 4 | (initial setup sys 4)
| 3 | n | n | 4 | (new setup sys 4)
| 4 | n | y | 5 | (new setup sys 5)
| 5 | y | y | 5 | (new setup sys 5)
is it possible to do this using SQL? any ideas how? SQL has never been my strongest point :(
edit: using SQL server 2012
If you're using SQL Server 2012 or newer, you can use LAG to find the previous value, and just use a CASE on whether the old and new value differ;
WITH cte AS (
SELECT snr, sys,
lense, LAG(lense) OVER (PARTITION BY sys ORDER BY snr) old_lense,
camera, LAG(camera) OVER (PARTITION BY sys ORDER BY snr) old_camera
FROM table1
)
SELECT snr, sys,
CASE WHEN lense <> old_lense THEN 'y' ELSE 'n' END lense,
CASE WHEN camera <> old_camera THEN 'y' ELSE 'n' END camera
FROM cte
ORDER BY snr;
An SQLfiddle to test with.

Vertical headers in RestructuredText tables

In RestructuredText, you can render a header row in a table like this (taken from the documentation :
+------------------------+------------+----------+----------+
| Header row, column 1 | Header 2 | Header 3 | Header 4 |
| (header rows optional) | | | |
+========================+============+==========+==========+
| body row 1, column 1 | column 2 | column 3 | column 4 |
+------------------------+------------+----------+----------+
| body row 2 | Cells may span columns. |
+------------------------+------------+---------------------+
| body row 3 | Cells may | - Table cells |
+------------------------+ span rows. | - contain |
| body row 4 | | - body elements. |
+------------------------+------------+---------------------+
Is it possible to do the something similar with the first column?
An example, which clearly doesn't work, could be the following (note the double like at the end of column 1):
+------------------------++------------+----------+----------+
| Header row, column 1 || Header 2 | Header 3 | Header 4 |
| (header rows optional) || | | |
+========================++============+==========+==========+
| body row 1, column 1 || column 2 | column 3 | column 4 |
+------------------------++------------+----------+----------+
| body row 2 || Cells may span columns. |
+------------------------++------------+---------------------+
| body row 3 || Cells may | - Table cells |
+------------------------++ span rows. | - contain |
| body row 4 || | - body elements. |
+------------------------++------------+---------------------+
You may achieve this using list-table directive with option stub-columns. Or, you may even combine stub-columns with header-rows. See the http://docutils.sourceforge.net/docs/ref/rst/directives.html#list-table for the details. Hereafter is a simple example:
.. list-table:: Sample list table
:widths: 10 20 20
:header-rows: 1
:stub-columns: 1
* -
- Column 1
- Column 2
* - Row 1
- Hello
- World!
* - Row 2
- Hello
- List Table!
* - Row 3
- This
- Works
An obvious disadvantage is that you need to maintain table content as a list, which may be not that much convenient as with regular simple tables. So, you might want to check out the csv-table directive here: http://docutils.sourceforge.net/docs/ref/rst/directives.html#id1 , which also has option stub-columns.
If you need to stick to regular tables syntax - sorry, I'm not sure this is possible. As a workaround - you can use strong emphasis for text in the first column :-)

Resources