Randomly Select a Row with SQL in Access - sql

I have a small access database with some tables. I am trying the code in the sql design within access. I just want to randomly select a record within a table.
I created a simple table called StateAbbreviation. It has two columns: ID and Abbreviation. ID is just an autonumber and Abbreviation are different abbreviations for states.
I saw this thread here. So I tried
SELECT Abbreviation
FROM STATEABBREVIATION
ORDER BY RAND()
LIMIT 1;
I get the error Syntax error (missing operator) in query expresion RAND() LIMIT 1. So I tired RANDOM() instead of RAND(). Same error.
None of the others worked either. What am I doing wrong? Thanks.

Ypercude provided a link that led me to the right answer below:
SELECT TOP 1 ABBREVIATION
FROM STATEABBREVIATION
ORDER BY RND(ID);
Note that for RND(), I believe that it has to be an integer value/variable.

You need both a variable and a time seed to not get the same sequence(s) each time you open Access and run the query - and to use Access SQL in Access:
SELECT TOP 1 Abbreviation
FROM STATEABBREVIATION
ORDER BY Rnd(-Timer()*[ID]);
where ID is the primary key of the table.

Please try this, it is helpful to you
It is possible by using a stored procedure and function, which I created it's have a extra column which you could be create in your table FLAG name and column all field value should be 0 Then it works
create Procedure proc_randomprimarykeynumber
as
declare #Primarykeyid int
select top 1
#Primarykeyid = u.ID
from
StateAbbreviation u
left join
StateAbbreviation v on u.ID = v.ID + 1
where
v.flag = 1
if(#Primarykeyid is null )
begin
UPDATE StateAbbreviation
SET flag = 0
UPDATE StateAbbreviation
SET flag = 1
WHERE ID IN (SELECT TOP 1 ID
FROM dbo.StateAbbreviation)
END
ELSE
BEGIN
UPDATE StateAbbreviation
SET flag = 0
UPDATE StateAbbreviation
SET flag = 1
WHERE ID IN (#Primarykeyid)
END
SET #Primarykeyid = 1
SELECT TOP 1
ID, Abbreviation
FROM
StateAbbreviation
WHERE
flag = 1
It is made in stored procedure run this and get serial wise primary key
exec proc_randomprimarykeynumber
Thanks and regard

Try this:
SELECT TOP 1 *
FROM tbl_name
ORDER BY NEWID()
Of course this may have performance considerations for large tables.

Related

SQL - Operator IN with operator WITH AS

Using postgres
The following SQL creates TestsTodo, having all the informations about a table tests.
It also have a TestsTodoIds, having only the ids of TestsTodo
Then, i want to update all the rows of a table "test_results", with all the ids in TestsTodoIds. I can do it by setting "WHERE test_id IN (select id from TestsTodo)" But i cant do it with "WHERE test_id IN TestsTodoIds", which is basically the same, i don't understand why.
WITH
TestsTodo AS
(
-- Selecting from table tests
),
TestsTodoIds AS
(
SELECT id FROM TestsTodo -- This returns all the. ids from TestsTodo
)
--UPDATE test_results
--SET status = 'FOUND_IN_DB'
--WHERE test_id IN (SELECT id FROM TestsTodo)
--RETURNING *
-- This works
UPDATE test_results
SET status = 'FOUND_IN_DB'
WHERE test_id IN TestsTodoIds
RETURNING * -- This does not
Error: ERROR: syntax error at or near "TestsTodoIds"
LINE 31: WHERE test_id IN TestsTodoIds
^
Your CTE called TestsTodoIds is a virtual table with one column. It isn't a set of values, and IN needs a set of values. You could use
WHERE test_id IN (SELECT id FROM TestsTodoIds)
and your query would function correctly.
That CTE is, in my opinion, unnecessary. The WHERE clause I suggested will perform exactly the same as
WHERE test_id IN (SELECT id FROM TestsTodo)
and you'll have less complexity to cope with when reading and reasoning about the query.

Duplicate ID in the database

I noticed in my database, some users have the same ID number (it seems to be a bug that didn't check if the id number was already taken for a deleted user).
There are hundreds of couples of users with the same ID number.
Through SQL I would like to update (adding a 0) to all those users who have a duplicate ID and are deleted.
I'm very familiar with the SQL language.
I found all the duplicate ID users using this query, but I am not sure how I should proceed.
SELECT ID, COUNT(*) As Num
FROM Users
GROUP BY ID
HAVING COUNT(ID) >= 2
If I understand correctly, you have some sort of "isdeleted" flag. Although I'm not sure that "adding a zero" is the best solution to your problem, the standard SQL for this would, based on your description, look something like this:
update t
set id = id || '0'
where isdeleted = 1 and
exists (select 1 from t t2 where t2.id = t.id and t2.isdeleted = 0);
This assumes that isdeleted is a number, with 0 for false and 1 for true. || is the standard SQL operator for string concatenation. Some databases have other mechanisms for string concatenation.
The query is for oracle, not sure what database are you using,
update users set id = id||0 where rowid not in
(select max(rowid ) from users group by id)
--and flag = 'Deleted Flag' -- uncomment the delete flag if you have in the table. If not just use same query a it is
;

Update columns in DB2 using randomly chosen static values provided at runtime

I would like to update rows with values chosen randomly from a set of possible values.
Ideally I would be able to provide this values at runtime, using JdbcTemplate from Java application.
Example:
In a table, column "name" can contain any name. The goal is to run through the table and change all names to equal to either "Bob" or "Alice".
I know that this can be done by creating a sql function. I tested it and it was fine but I wonder if it is possible to just use simple query?
This will not work, seems that the value is computed once, and applied to all rows:
UPDATE test.table
SET first_name =
(SELECT a.name
FROM
(SELECT a.name, RAND() idx
FROM (VALUES('Alice'), ('Bob')) AS a(name) ORDER BY idx FETCH FIRST 1 ROW ONLY) as a)
;
I tried using MERGE INTO, but it won't even run (possible_names is not found in SET query). I am yet to figure out why:
MERGE INTO test.table
USING
(SELECT
names.fname
FROM
(VALUES('Alice'), ('Bob'), ('Rob')) AS names(fname)) AS possible_names
ON ( test.table.first_name IS NOT NULL )
WHEN MATCHED THEN
UPDATE SET
-- select random name
first_name = (SELECT fname FROM possible_names ORDER BY idx FETCH FIRST 1 ROW ONLY)
;
EDIT: If possible, I would like to only focus on fields being updated and not depend on knowing primary keys and such.
Db2 seems to be optimizing away the subselect that returns your supposedly random name, materializing it only once, hence all rows in the target table receive the same value.
To force subselect execution for each row you need to somehow correlate it to the table being updated, for example:
UPDATE test.table
SET first_name =
(SELECT a.name
FROM (VALUES('Alice'), ('Bob')) AS a(name)
ORDER BY RAND(ASCII(SUBSTR(first_name, 1, 1)))
FETCH FIRST 1 ROW ONLY)
or may be even
UPDATE test.table
SET first_name =
(SELECT a.name
FROM (VALUES('Alice'), ('Bob')) AS a(name)
ORDER BY first_name, RAND()
FETCH FIRST 1 ROW ONLY)
Now that the result of subselect seems to depend on the value of the corresponding row in the target table, there's no choice but to execute it for each row.
If your table has a primary key, this would work. I've assumed the PK is column id.
UPDATE test.table t
SET first_name =
( SELECT name from
( SELECT *, ROW_NUMBER() OVER(PARTITION BY id ORDER BY R) AS RN FROM
( SELECT *, RAND() R
FROM test.table, TABLE(VALUES('Alice'), ('Bob')) AS d(name)
)
)
AS u
WHERE t.id = u.id and rn = 1
)
;
There might be a nicer/more efficient solution, but I'll leave that to others.
FYI I used the following DDL and data to test the above.
create table test.table(id int not null primary key, first_name varchar(32));
insert into test.table values (1,'Flo'),(2,'Fred'),(3,'Sue'),(4,'John'),(5,'Jim');

Adding integer increment after string for missing values ms-access

I have a dataset containing road names and road types. There are many missing road names and I would like to populate missing names with a simple string declaring road type followed by a Unique integer identifier as exemplified below.
Path1
Path2
Path...
I am trying to use the declare function, but something is not correct in my statement.
DECLARE #i int
SET #i=0
UPDATE KMS_VEJMIDT_BRUDT
SET VEJNAVN = "Sti"+Str(#i), #i=#i+1
WHERE (((KMS_VEJMIDT_BRUDT.VEJNAVN) Is Null) AND ((KMS_VEJMIDT_BRUDT.VEJMTYPE)="Sti"));
Edit: I misread the question slightly - I've added "Sti" as a prefix for the generated numbers, and started at 1
You may be able to do this in a 3 step process as described in this answer. I'm assuming that you have an ID primary key field in the KMS_VEJMIDT_BRUDT table.
Step 1:
Make a SELECT query named GENERATE_NEXT_NAVN using the following SQL:
SELECT C.ID, "Sti"&[RowNo] AS NEXT_VEJNAVN
FROM (SELECT A.ID,
A.VEJMTYPE,
(select count(*) from KMS_VEJMIDT_BRUDT as B where A.ID>=B.ID AND B.VEJNAVN Is Null and A.VEJMTYPE = "Sti" ) AS RowNo
FROM KMS_VEJMIDT_BRUDT AS A
WHERE A.VEJNAVN Is Null
and A.VEJMTYPE = "Sti"
) AS C;
Note the use of a Row Number workaround as described in this answer. I use this to generate an incrementing number starting from the highest NAVN present in the source table.
Step 2:
Copy the query output from Step 1 into a temporary table:
SELECT GENERATE_NEXT_NAVN.*
INTO NEXT_NAVN_TEMP
FROM GENERATE_NEXT_NAVN;
Step 3:
Update the source table using the values in the temp table:
UPDATE KMS_VEJMIDT_BRUDT
INNER JOIN NEXT_NAVN_TEMP
ON KMS_VEJMIDT_BRUDT.ID = NEXT_NAVN_TEMP.ID
SET KMS_VEJMIDT_BRUDT.VEJNAVN = [NEXT_NAVN_TEMP].[NEXT_VEJNAVN];

teradata case when issue

I have the following queries which are supposed to give the same result, but drastically different
1.
select count(*)
from qigq_sess_parse_2
where str_vendor = 'natural search' and str_category is null and destntn_url = 'http://XXXX.com';
create table qigq_test1 as
(
select case
when (str_vendor = 'natural search' and str_category is null and destntn_url = 'http://XXXX.com' ) then 1
else 0
end as m
from qigq_sess_parse_2
) with data;
select count(*) from qigq_test1 where m = 1;
the first block gives a total number of count 132868, while the second one only gives 1.
What are the subtle parts in the query that causes this difference?
Thanks
When you create a table in Teradata, you can specify it to be SET or MULTISET. If you don't specify, it defaults to SET. A set table cannot contain duplicates. So at most, your new table will contain two rows, a 0 and a 1, since that's all that can come from your case statement.
EDIT:
After a bit more digging, the defaults aren't quite that simple. But in any case, I suspect that if you add the MULTISET option to your create statement, you'll see the behavior your expect.
My guess would be that your Create Table statement is only pulling in one row of data that fits the parameters for the following Count statement. Try this instead:
CREATE TABLE qigq_test1 (m integer);
INSERT INTO qigq_test1
SELECT
CASE
WHEN (str_vendor = 'natural search' and str_category IS NULL AND destntn_url = 'http://XXXX.com' ) THEN 1
ELSE 0
END AS m
FROM qigq_sess_parse_2;
SELECT COUNT(*) FROM qigq_test1 WHERE m = 1;
This should pull ALL ROWS of data from qigq_sess_parse_2 into qigq_test1 as either a 0 or 1.