Trying to get one Column from random query in sqlite - sqlite

Hello I have the following query in SQLite. ISBN is a text variable.
insert into BOOK_ORDER
SELECT OrderID FROM tableOrder WHERE OrderID = 1 UNION SELECT ISBN FROM BOOK ORDER BY random() LIMIT 1;
I am trying to add two columns together
However I get an error:
1st ORDER BY term does not match any column in the result set:
insert into BOOK_ORDER
SELECT OrderID FROM tableOrder WHERE OrderID = 1 UNION SELECT ISBN FROM BOOK
ORDER BY random() LIMIT 1;
I want to have a two column result table:
OrderID ISBN
4 192374125
EDIT:
I think I need to use a cross join, can someone help me?

UNION results in more rows (unless they are duplicates).
To get more columns, you have to list all of them in the SELECT clause.
In this case, you can use subqueries:
insert into BOOK_ORDER
VALUES ((SELECT OrderID FROM tableOrder WHERE OrderID = 1),
(SELECT ISBN FROM BOOK ORDER BY random() LIMIT 1));

Related

Would these two SQLite queries generate the same result?

I'm working through this exercise.
On question 4, the goal is to find employees hired after "Jones". I think this problem can be solved without a join like so:
SELECT first_name, last_name, hire_date
FROM employees
WHERE hire_date > (
SELECT hire_date FROM employees WHERE last_name = "Jones"
)
But the answer on the website suggests:
SELECT e.first_name, e.last_name, e.hire_date
FROM employees e
JOIN employees davies
ON (davies.last_name = "Jones")
WHERE davies.hire_date < e.hire_date;
Are these more-or-less the same or is there a reason the second answer should be considered better?
I assume that the column last_name is defined as UNIQUE, so that the subquery in the 1st query returns only 1 row.
If not, then the queries do not return the same results, because although the subquery in the 1st query may return more than 1 row (and in other databases the query would not even run), SQLite will pick just the 1st of the returned rows and use its hire_date to compare it with all the rows of the table, while the join will use all the rows where last_name = "Jones".
If my assumption is correct then the 2 queries are equivalent, but the 1st one is what I would suggest because it is more readable and I believe it would perform better than the join.
If I had to use a join for this requirement (since it is homework) I would choose a more readable form:
SELECT e.first_name, e.last_name, e.hire_date
FROM employees e
JOIN (SELECT * FROM employees WHERE last_name = "Jones") t
ON t.hire_date < e.hire_date;

How to write an SQLite query that uses 4 tables and count()?

I've got 4 tables that I want data from.
Trip_T
tripID (PK)
userID (FK)
...
User_T
userID (PK)
username
...
Excursion_T
excursionID (PK)
tripID (FK)
...
POI_T
poiID (PK)
excursionID (FK)
...
I want to create a table with one row for each trip in the db.
Each row should include the tripID, title, the user's name associated with the trip, the number of excursions made on the the trip and the number of poi (points of interest) associated with those excursions.
I'm using the following query:
SELECT Trip_T.tripID, Trip_T.title, User_T.username
COUNT(DISTINCT Excursion_T.excursionID) AS numExcursions,
COUNT(DISTINCT POI_T.poiID) AS numPOI
FROM Trip_T
INNER JOIN User_T ON User_T.userID = Trip_T.userID
INNER JOIN Excursion_T ON Excursion_T.tripID = Trip_T.tripID
INNER JOIN POI_T ON POI_T.excursionID = Excursion_T.excursionID
Even though I have multiple trips in the db, each with multiple excursions and pois, the query returns 1 row with what looks like the total number of excursions and total number of pois for all trips.
Any help is appreciated.
You forgot to add grouping to your query:
GROUP BY Trip_T.tripID, Trip_T.title, User_T.username
This way the counters correspond to each triplet of (Trip_T.tripID, Trip_T.title, User_T.username)

How to write query with multiple conditions?

I have table with column fields date,points and categoryType.
How to write sqlite query to get records from table in between given date
where points value are greater then Zero ( > 0).
Select * from tableName
where (Select points FROM tableName
WHERE date(DateValue) BETWEEN date('2016-12-26') AND date('2016-12-27')
> 0)
A subquery would make sense only if it were correlated.
Just use a simple query, and combine multiple conditions with AND:
SELECT *
FROM MyTable
WHERE date(DateValue) BETWEEN '2016-12-26' AND '2016-12-27'
AND points > 0;

find count of distinct values in a column

Hi all am trying to build a sql query to display some information on a dashboard.
I have a table in which i store my sales data.My query needs to find total sales in last 7 days,average and group it based on region(which is present in user table.) .I created a temp table to get the item sales.DashBoard_Items table contains particular item that needs to be shown on dashboard.Now my problem is i need to get the store count of each region to find average sales.Can some one please help
Declare #TableTest
table(itemid int,itemname varchar(100),itemdescription varchar(100),id int,itemidd int,userid int,orderdate varchar(40),qty int)
insert into #TableTest
select * from DashBoard_Items join
SalesQTY on SalesQTY.OrderDate>= CONVERT(varchar(10) , DATEADD(DAY,-7,GETDATE()),126)
and OOS_DashBoard_CoreItems.itemid=SalesQTY.itemid
select distinct t.userid,u.region from #TableTest t join users u on t.userid=u.userid and region is not null
above select query returns
how can i get region count from the above select query
region count
5 - SUN WEST 2
2 - LONG ISLAND 3
You need to group by region and then use cont(*)
SELECT region, count(*)
FROM #TableTest
GROUP BY region;
Please try:
SELECT
Region,
COUNT(*) AS [Count]
FROM YourTable
GROUP BY Region
OR
SELECT
DISTINCT Region,
COUNT(*) OVER (PARTITION BY Region) AS [Count]
FROM YourTable
SELECT u.region, COUNT(*)
FROM #TableTest t JOIN users u ON t.userid=u.userid AND u.region IS NOT NULL
GROUP BY u.region
try
SELECT region, count( * )
FROM mytable
GROUP BY region

Select random row from a sqlite table

I have a sqlite table with the following schema:
CREATE TABLE foo (bar VARCHAR)
I'm using this table as storage for a list of strings.
How do I select a random row from this table?
Have a look at Selecting a Random Row from an SQLite Table
SELECT * FROM table ORDER BY RANDOM() LIMIT 1;
The following solutions are much faster than anktastic's (the count(*) costs a lot, but if you can cache it, then the difference shouldn't be that big), which itself is much faster than the "order by random()" when you have a large number of rows, although they have a few inconvenients.
If your rowids are rather packed (ie. few deletions), then you can do the following (using (select max(rowid) from foo)+1 instead of max(rowid)+1 gives better performance, as explained in the comments):
select * from foo where rowid = (abs(random()) % (select (select max(rowid) from foo)+1));
If you have holes, you will sometimes try to select a non-existant rowid, and the select will return an empty result set. If this is not acceptable, you can provide a default value like this :
select * from foo where rowid = (abs(random()) % (select (select max(rowid) from foo)+1)) or rowid = (select max(rowid) from node) order by rowid limit 1;
This second solution isn't perfect : the distribution of probability is higher on the last row (the one with the highest rowid), but if you often add stuff to the table, it will become a moving target and the distribution of probabilities should be much better.
Yet another solution, if you often select random stuff from a table with lots of holes, then you might want to create a table that contains the rows of the original table sorted in random order :
create table random_foo(foo_id);
Then, periodicalliy, re-fill the table random_foo
delete from random_foo;
insert into random_foo select id from foo;
And to select a random row, you can use my first method (there are no holes here). Of course, this last method has some concurrency problems, but the re-building of random_foo is a maintainance operation that's not likely to happen very often.
Yet, yet another way, that I recently found on a mailing list, is to put a trigger on delete to move the row with the biggest rowid into the current deleted row, so that no holes are left.
Lastly, note that the behavior of rowid and an integer primary key autoincrement is not identical (with rowid, when a new row is inserted, max(rowid)+1 is chosen, wheras it is higest-value-ever-seen+1 for a primary key), so the last solution won't work with an autoincrement in random_foo, but the other methods will.
You need put "order by RANDOM()" on your query.
Example:
select * from quest order by RANDOM();
Let's see an complete example
Create a table:
CREATE TABLE quest (
id INTEGER PRIMARY KEY AUTOINCREMENT,
quest TEXT NOT NULL,
resp_id INTEGER NOT NULL
);
Inserting some values:
insert into quest(quest, resp_id) values ('1024/4',6), ('256/2',12), ('128/1',24);
A default select:
select * from quest;
| id | quest | resp_id |
1 1024/4 6
2 256/2 12
3 128/1 24
--
A select random:
select * from quest order by RANDOM();
| id | quest | resp_id |
3 128/1 24
1 1024/4 6
2 256/2 12
--*Each time you select, the order will be different.
If you want to return only one row
select * from quest order by RANDOM() LIMIT 1;
| id | quest | resp_id |
2 256/2 12
--*Each time you select, the return will be different.
What about:
SELECT COUNT(*) AS n FROM foo;
then choose a random number m in [0, n) and
SELECT * FROM foo LIMIT 1 OFFSET m;
You can even save the first number (n) somewhere and only update it when the database count changes. That way you don't have to do the SELECT COUNT every time.
Here is a modification of #ank's solution:
SELECT *
FROM table
LIMIT 1
OFFSET ABS(RANDOM()) % MAX((SELECT COUNT(*) FROM table), 1)
This solution also works for indices with gaps, because we randomize an offset in a range [0, count). MAX is used to handle a case with empty table.
Here are simple test results on a table with 16k rows:
sqlite> .timer on
sqlite> select count(*) from payment;
16049
Run Time: real 0.000 user 0.000140 sys 0.000117
sqlite> select payment_id from payment limit 1 offset abs(random()) % (select count(*) from payment);
14746
Run Time: real 0.002 user 0.000899 sys 0.000132
sqlite> select payment_id from payment limit 1 offset abs(random()) % (select count(*) from payment);
12486
Run Time: real 0.001 user 0.000952 sys 0.000103
sqlite> select payment_id from payment order by random() limit 1;
3134
Run Time: real 0.015 user 0.014022 sys 0.000309
sqlite> select payment_id from payment order by random() limit 1;
9407
Run Time: real 0.018 user 0.013757 sys 0.000208
SELECT bar
FROM foo
ORDER BY Random()
LIMIT 1
I came up with the following solution for the large sqlite3 databases:
SELECT * FROM foo WHERE rowid = abs(random()) % (SELECT max(rowid) FROM foo) + 1;
The abs(X) function returns the absolute value of the numeric argument
X.
The random() function returns a pseudo-random integer between
-9223372036854775808 and +9223372036854775807.
The operator % outputs the integer value of its left operand modulo its right operand.
Finally, you add +1 to prevent rowid equal to 0.

Resources