How to select the next 50 records from a specified row in an SQLite table - sqlite

Consider that my SQLite table has the following schema,
|'''''''''''''''''''''''''''''''''''''
| unique_id(TXT) | object_data(BLOB) |
|'''''''''''''''''''''''''''''''''''''
| | |
| | |
| | |
''''''''''''''''''''''''''''''''''''''
Assume that the row_id property is enabled, and so my question is, for a given unique_id, is it possible to fetch the next 50 records from the table,
using a single SQL query? (Using the row_id property)

Try getting result through this method.
Select * from table_name [WHERE conditions] Limit 50 offset (Select row_id from table_name where unique_id = x);

Related

Storing attributes with multiple values in relational database

I am storing product attributes in a relational table in a MariaDB database the following way:
I have a main table, called Products which provide the name, description, and other simple information about a product, and another table, ProductAttributes, with the following structure: Id|ProductId|Attribute|Value where Id is an autoincremented primary key, and ProductId is a reference to a row in the Products table.
I can store simple attribute value relations to a product in this way, say ie, height, weight, length of a product. My problems start, when a product's attribute, ie color can have multiple possible values.
I could add multiple lines to the ProductAttributes table when storing multi-valued attributes, ie:
1|yy|color|red
2|yy|color|blue
and from this schema, I could easily retrieve a single product's attributes, but I am having trouble on how to go forward when trying to compare two products based on their attributes.
Is there any other way to store multiple values for a single attribute in a relational database to maintain their searchability?
As of now, to find similar attributed products I am doing a similar query:
SELECT * FROM ProductAttributes base
INNER JOIN ProductAttributes compare ON compare.ProductId != base.ProductId
WHERE base.Attribute = compare.Attribute
AND base.Value = compare.Value
AND base.ProductId = 'x'
GROUP BY compare.ProductId
My problem is, that this query will return the products with a red and blue color, as similar to products with a blue color.
Btw, I can not change my attributes tables to a one attribute per column representation, because I do not know from the get-go how many attributes will I have, and even if I knew, I have way too many possible attributes and differences on each product category, to represent this in a traditional table.
A possible pitfall is, that I also want to compare products to one another with missing attributes. Ie, if a product has a length attribute specified, but another one has no length attribute, they could still be similar. Right now, to make this kind of comparison, in the background, I am transposing my attributes table, to a simple table, and on that table, perform this query:
SELECT b.ProductId as BaseProduct, s.ProductId as SimProduct
FROM tmp_transposed_product_attributes b
CROSS JOIN tmp_transposed_product_attributes s ON b.ProductId != s.ProductId
WHERE (b.attribute1 = s.attribute1 OR b.attribute1 IS NULL OR s.attribute1 IS NULL)
AND (b.attribute2 = s.attribute2 OR b.attribute2 IS NULL OR s.attribute2 IS NULL) ...
If I'm following correctly for the product comparison, I like to use EXISTS or NOT EXISTS to help find things like that, which may also help avoid having to transpose the data.
For example, given this sample table data:
MariaDB [test]> select * from productattributes;
+----+-----------+-----------+-------+
| id | productID | attribute | value |
+----+-----------+-----------+-------+
| 1 | yy | height | 5 |
| 2 | yy | color | red |
| 3 | yy | weight | 10 |
| 4 | yy | length | 6 |
| 5 | yy | color | blue |
| 6 | zz | color | white |
| 7 | zz | height | 5 |
| 8 | zz | length | 8 |
+----+-----------+-----------+-------+
8 rows in set (0.00 sec)
To find all similar attributes between the two, but has different values (removes attribute/values pairs that are the same) use a NOT EXISTS query to same table like so:
MariaDB [test]> SELECT * FROM `productattributes` pA
-> WHERE productID IN ('yy', 'zz')
-> AND NOT EXISTS (SELECT * FROM productattributes pB
-> WHERE pA.attribute = pB.attribute
-> AND pA.value = pB.value
-> AND pA.productID != pB.productID)
-> ORDER BY productID, attribute;
+----+-----------+-----------+-------+
| id | productID | attribute | value |
+----+-----------+-----------+-------+
| 2 | yy | color | red |
| 5 | yy | color | blue |
| 4 | yy | length | 6 |
| 3 | yy | weight | 10 |
| 6 | zz | color | white |
| 8 | zz | length | 8 |
+----+-----------+-----------+-------+
6 rows in set (0.00 sec)
Then to find attribute/value pairs that ARE the same between the two, simply remove the NOT portion of the query:
MariaDB [test]> SELECT * FROM `productattributes` pA
-> WHERE productID IN ('yy', 'zz')
-> AND EXISTS (SELECT * FROM productattributes pB
-> WHERE pA.attribute = pB.attribute
-> AND pA.value = pB.value
-> AND pA.productID != pB.productID)
-> ORDER BY productID, attribute;
+----+-----------+-----------+-------+
| id | productID | attribute | value |
+----+-----------+-----------+-------+
| 1 | yy | height | 5 |
| 7 | zz | height | 5 |
+----+-----------+-----------+-------+
2 rows in set (0.00 sec)
Here's the query without the command line junk:
SELECT * FROM `productattributes` pA
WHERE productID IN ('yy', 'zz')
AND NOT EXISTS (SELECT * FROM productattributes pB
WHERE pA.attribute = pB.attribute
AND pA.value = pB.value
AND pA.productID != pB.productID)
ORDER BY productID, attribute;
EDIT:
To cover the case where there is an attribute that is in one but not the other, then the value check of the query can be removed:
MariaDB [test]> SELECT * FROM `productattributes` pA
-> WHERE productID IN ('yy', 'zz')
-> AND NOT EXISTS (SELECT * FROM productattributes pB
-> WHERE pA.attribute = pB.attribute
-> AND pA.productID != pB.productID)
-> ORDER BY productID, attribute;
+----+-----------+-----------+-------+
| id | productID | attribute | value |
+----+-----------+-----------+-------+
| 3 | yy | weight | 10 |
+----+-----------+-----------+-------+
1 row in set (0.00 sec)

Sqlite INSERT OR REPLACE is incrementing rowid

I am using the INSERT OR REPLACE syntax to either insert or update a row that may exist based on a unique column constraint within the table.
The table structure is
| Name | Age | CustomerId (unique) |
When I print out the table the first time, I get something like
| Name | Age | CustomerId | rowid |
|"Bob" | 22 | 5 | 1 |
Then I run INSERT OR REPLACE INTO MyTable(Name, Age, CustomerId) VALUES ("Bob", 23, 5);"
Without fail, this will increment the rowid column each time it is run. So now the result is
| Name | Age | CustomerId | rowid |
|"Bob" | 23 | 5 | 2 |
How do I prevent rowid from incrementing?
This is how INSERT OR REPLACE works.
If a violation of a unique index/constraint occurs then the existing row is deleted and the new row is inserted, so a new rowid is assigned for the new row.
If you don't want this to happen you must use UPSERT:
insert into tablename(Name, Age, CustomerId) values ('Bob', 23, 5)
on conflict(CustomerId) do update
set Name = excluded.Name,
Age = excluded.Age;
See the demo.

How to get ID from table A to table B in trigger?

I have two tables, A & B:
TABLE A
id | name
TABLE B
id | name | fk_idA
I want to create trigger AFTER INSERT in TABLE B which updates fk_idA appropriate with the newest id from table A.
An example:
TABLE A
id | name
1 | Andrew
2 | David
TABLE B
id | name | fk_idA
1 | Photo1 | 2
If the ID column is autoincrementing, the latest is the largest one, i.e., the one returned by MAX:
CREATE TRIGGER DefaultAIsLatest
AFTER INSERT ON TableB
FOR EACH ROW
WHEN NEW.fk_idA IS NULL
BEGIN
UPDATE TableB
SET fk_idA = (SELECT MAX(id)
FROM TableA)
WHERE id = NEW.id;
END;

selecting a row based on a number of column values in SQLite

I have a table with this structure:
id | IDs | Name | Type
1 | 10 | A | 1
2 | 11 | B | 1
3 | 12 | C | 2
4 | 13 | D | 3
except id nothing else is a FOREIGN or PRIMARY KEY. I want to select a row based on it's column values that are not PRIMARY KEY. I have tried the following syntax but it yields no results.
SELECT * FROM MyTable WHERE Name = 'A', Type = 1;
what am I doing wrong? What is exactly returned by a SELECT statement? I'm totally new to Data Base and I'm currently experimenting and trying to learn it. so far my search has not yield any results regarding this case.
Use and to add multiple conditions to your query
SELECT *
FROM MyTable
WHERE Name = 'A'
AND Type = 1;

Passing result variable to nested SELECT statement in Sqlite

I have the following query which works:
SELECT
SoftwareList,
Count (SoftwareList) as Count
FROM [assigned]
GROUP BY SoftwareList
This returns the following result set:
*SoftwareList* | *Count*
--------------------------
Office XP | 3
Adobe Reader | 3
Dreamewaver | 2
I can also run the following query:
SELECT
GROUP_CONCAT(LastSeen) as LastSeen
FROM [assigned]
WHERE SoftwareList = 'Dreamweaver';
Which would return the following result set:
*LastSeen*
----------
2007-9-23,2012-3-12
I wish to combine both of these queries into one, so that the following results are returned:
*SoftwareList* | *Count* | *LastSeen*
--------------------------------------------------------
Office XP | 3 | 2001-2-12,2008-3-19,2002-2-17
Adobe Reader | 3 | 2008-2-12,2009-3-20,2007-3-16
Dreamewaver | 2 | 2007-9-23,2012-3-12
I am trying this but don't know how to refer to the initial SoftwareList variable within the nested statement:
SELECT
SoftwareList,
Count (SoftwareList) as Count,
(SELECT
GROUP_CONCAT(LastSeen) FROM [assigned]
WHERE SoftwareList = SoftwareList
) as LastSeen
FROM [assigned]
GROUP BY SoftwareList;
How can I pass SoftwareList which is returned for each row, into the nested statement?
I think this is what you want:
SELECT SoftwareList, COUNT(SoftwareList) AS Count, GROUP_CONCAT(LastSeen)
FROM assigned GROUP BY SoftwareList

Resources