I have a 200k rows mysql table, and a column with empty value, and i like to populate this column with random numbers from 1 to 10,000.
I don't know if its possible to have a query something like this:
UPDATE 'videos'
SET 'views' = rand(1,10000)
RAND() produces random float values from 0 to 1. Could you try this?
Update videos set views = CAST(RAND() * 10000 AS UNSIGNED)
Try this one. It can generate a random number between 1 to 10000.
UPDATE videos
SET views = FLOOR(rand() * 10000) + 1;
Or this:
UPDATE videos SET views = FLOOR(1 + rand() * 10000 );
updating Table records with random phone numbers
DECLARE #OrderDetailID INT
DECLARE #Phone VARCHAR(100)
DECLARE MY_CURSOR CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT DISTINCT
OrderDetailID
FROM dbo.OrderDetailTBL
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO #OrderDetailID
WHILE ##FETCH_STATUS = 0
BEGIN
--Do something with Id here
SET #Phone = '(' + CONVERT(VARCHAR(3), CONVERT(NUMERIC(3, 0), RAND()
* 899)) + ') ' + CONVERT(VARCHAR(3), CONVERT(NUMERIC(3, 0), RAND()
* 899)) + '-' + CONVERT(VARCHAR(4), CONVERT(NUMERIC(4, 0), RAND()
* 8999))
UPDATE dbo.OrderDetailTBL
SET ShippingPhone = #Phone
WHERE OrderDetailID = #OrderDetailID
FETCH NEXT FROM MY_CURSOR INTO #OrderDetailID
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
If you wants to update one column with random number between some range and having -Ve type too, then you can use the below code :
UPDATE DataBase.TableName
SET Column = ((4 * RAND()) - (4 * RAND()))
WHERE IndexColumn > 0; -- here I have taken range between 4 to -4
Related
I have column named Column1 looks like this:
ABCABC321
ABCABC213
ABC478
ABC474
Here is a query to show all extra characters of 'ABC'
select * from TABLE where Column like 'ABCABC%';
This is the output:
ABCABC321
ABCABC213
How can I delete the extra 'ABC' for all records from the query used above?
This is the desired output:
ABC321
ABC213
ABC478
ABC474
UPDATE your_table
SET your_column = RIGHT(your_column, CHAR_LENGTH(your_column) - 3)
WHERE your_column LIKE 'ABCABC%';
Use a case condition and the SUBSTRING function to read a string value from the 4th character (ignoring the first 3):
select
case when Column1 like 'ABCABC%'
then substring(Column1, 4)
else Column1
end as Column1
from Table1
See demon on db-fiddle
Using STUFF Function:
Update #table_name
set #column_name = Stuff(#column_name, 1, 3, '')
where #column_name like 'ABCABC%';
create function [dbo].[RemoveAllRepeatingChars](
#input_string varchar(2000))
returns varchar(2000)
as
begin
declare #output_string varchar(2000)=''
declare #index int
declare #current_char char(1) = 0
declare #previous_chars varchar(2000) = ''
set #output_string = ''
set #index = 1
--traverse input string
while #index <= len(#input_string)
begin
--get current character in string
set #current_char = substring(#input_string, #index, 1)
if charindex(#current_char, #previous_chars) = 0
begin
set #output_string = #output_string + substring(#input_string, #index, 1)
end
-- store all the characters for comparison
set #previous_chars = #previous_chars + substring(#input_string, #index, 1)
set #index = #index + 1
end
return #output_string
end
*****************************************************************
UPDATE your_table SET your_column = (select RemoveAllRepeatingChars(your_column)) WHERE your_column LIKE 'ABCABC%';
In the code below, I'm trying go through the results of endDateTable row by row, comparing the current row's endDate to the previous row's endDate. If there has been any change since the previous, we increment #revisionNum. However, upon populating the new table, all of the #revisionNum entries are 0. What am I doing wrong?
NOTE: I'm using prepared statements in this manner since doing a straightforward SELECT into a variable gives a syntax error due to the LIMIT clause not allowing a variable in our version of MySQL.
BEGIN
DECLARE _currentEndDate DATETIME DEFAULT now();
DECLARE _priorEndDate DATETIME DEFAULT now();
SET #ResultsCount = (SELECT COUNT(*) FROM mainTable);
SET #j = 0;
WHILE #j < #ResultsCount DO
SET #revisionNum = 0;
/*CURRENT END DATE*/
SET #appResultQueryCurrent = CONCAT('
SELECT
end_date
INTO _currentEndDate
FROM endDateTable
LIMIT ', #j, ', 1'
);
PREPARE currentQueryStmt FROM #appResultQueryCurrent;
EXECUTE currentQueryStmt;
/*PREVIOUS END DATE*/
SET #appResultQueryPrior = CONCAT('
SELECT
end_date
INTO _priorAppEndDate
FROM endDateTable
LIMIT ', IF(#j = 0, 0, #j - 1), ', 1'
);
PREPARE priorQueryStmt FROM #appResultQueryPrior;
EXECUTE priorQueryStmt;
SET #revisionNum = IF(
#j = 0 OR (_currentEndDate = _priorEndDate),
#revisionNum,
IF(
_currentEndDate != _priorEndDate,
#revisionNum + 1,
#revisionNum
)
);
INSERT INTO finalTable (RevisionNum)
SELECT
#revisionNum AS RevisionNum
FROM endDateTable;
SET #j = #j +1;
END WHILE;
END $$
You don't need a loop, you can use INSERT INTO ... SELECT ..., incrementing the variable in the select query.
You also need an ORDER BY criteria to specify how to order the rows when comparing one row to the previous row.
INSERT INTO finalTable (RevisionNum, otherColumn)
SELECT revision, otherColumn
FROM (
SELECT IF(end_date = #prev_end_date, #revision, #revision := #revision + 1) AS revision,
#prev_end_date := end_date,
otherColumn
FROM endDateTable
CROSS JOIN (SELECT #prev_end_date := NULL, #revision := -1) AS vars
ORDER BY id) AS x
DEMO
The offset value in the LIMIT clause is tenuous without an ORDER BY.
Without an ORDER BY clause, MySQL is free to return results in any sequence.
There is no guarantee that LIMIT 41,1 will return the row before LIMIT 42,1, or that it won't return the exact same row as LIMIT 13,1 did.
(A table in a relational database represents an unordered set of tuples, there is no guaranteed "order" or rows in a table.)
But just adding ORDER BY to the queries isn't enough to fix the Rube-Goldberg-esque rigmarole.
In the code shown, it looks like each time through the loop, we're inserting a copy of endDateTable into finalTable. If that's 1,000 rows in endDateTable, we're going to get 1,000,000 rows (1,000 x 1,000) inserted into finalTable. Not at all clear why we need so many copies.
Given the code shown, it's not clear what the objective is. Looks like we are conditionally incrementing revisionNum, the end result of which is the highest revision num. Just guessing here.
If there is some kind of requirement to do this in a LOOP construct, within a procedure, I'd think we'd do a cursor loop. And we can use procedure variables vs user-defined variables.
Something along these lines:
BEGIN
DECLARE ld_current_end_date DATETIME;
DECLARE ld_prior_end_date DATETIME;
DECLARE li_done INT;
DECLARE li_revision_num INT;
DECLARE lcsr_end_date CURSOR FOR SELECT t.end_date FROM `endDateTable` t ORDER BY NULL;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET li_done = TRUE;
SET li_done = FALSE;
SET li_revision_num = 0;
OPEN lcsr_end_date;
FETCH lcsr_end_date INTO ld_current_end_date;
SET ld_prior_end_date = ld_current_end_date;
WHILE NOT li_done DO
SET li_revision_num = li_revision_num + IF( ld_current_end_date <=> ld_prior_end_date ,0,1);
SET ld_prior_end_date := ld_current_end_date;
FETCH lcsr_end_date INTO ld_current_end_date;
END WHILE;
CLOSE lcsr_end_date;
INSERT INTO `finalTable` (revisionnum) VALUES (li_revision_num);
END $$
Note the "order by" clause on the SELECT, its not clear what the rows should be ordered on, so we're using a literal as a placeholder.
As the end result, we insert a single row into finalTable.
Again, it's not clear what the code in the question is supposed to achieve, but doing a cursor loop across ordered rows would be much more efficient than a bazillion dynamic SQL executions fetching individual rows.
How can I delete all records from all tables in a database, where the table has a column called systemid where systemid does not equal 1 or 2?
So I need to see if the table contains a certain column name, and if yes, check value of that column for all records, if not 1 or 2, delete. On all tables in the db.
Trying to clean-up a development db.
--- UPDATE ---
I found this SO thread: SQL Server : check if table column exists and remove rows
Which details the following:
IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1')
IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1' AND COLUMN_NAME = 'COL1')
delete TAB1 where COL1 not in (select COL2 from TAB2);
but I can't for the life of me correctly from a SQL query that can do what I wan to achieve due to both lack of knowledge and experience. Could anyone please provide a sample code with an explanation?
Thank you overflowers!
DECLARE #TableName VARCHAR(128);
DECLARE #MyColumn VARCHAR(128);
SET #MyColumn = 'MyColumnName'
DECLARE MyCursor CURSOR FOR
(SELECT OBJECT_NAME(c.id) as ObjectName
FROM dbo.syscolumns c
WHERE
OBJECTPROPERTY(c.id,'ISTABLE') = 1 --Search for tables only
AND c.name = #MyColumn)
OPEN MyCursor
FETCH NEXT FROM MyCursor into #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC
(
'DELETE ' + #MyColumn
+' FROM ' + #TableName
+' WHERE ' + #MyColumn + ' not in (1,2)'
)
FETCH NEXT FROM MyCursor into #TableName
END
CLOSE MyCursor
DEALLOCATE MyCursor
I am trying to decide whether to set min_word_length to be 2 or 3 on my new MySQL instance, so i figure if I count the number of 2 letter words in the column to be indexed it will give an indication of the right answer.
So, question is, is it possible using a SQL query to count the number two letter words within a column?
Not tested, but could you try
SELECT SUM(
CASE WHEN yourColumn REGEXP '[[:<:]][a-zA-Z]{2}[[:>:]]'
THEN 1
ELSE 0 END
) AS matches
FROM ...
Although I think, that it might only count if a 2-character-word is in a row, not how many times in one row.
UPDATE: Tested and it works like I thought, so please just ignore this answer.
The LEN() function returns the length of the value in a text field.
SELECT LEN(column_name) FROM table_name
The COUNT(*) function returns the number of records in a table:
SELECT COUNT(column_name) FROM table_name
So your query should be something like this :
SELECT COUNT(column_name) FROM table_name
WHERE LEN(column_name)=2
UPDATE:
Ok sorry I guess I misunderstood you. In the case you want it I'm afraid there is no build in functions to do what you want it to do. So you have to make a function on your own. Something like this should work:
CREATE FUNCTION [dbo].[WordCount] ( #InputString VARCHAR(4000) )
RETURNS INT
AS
BEGIN
DECLARE #Index INT
DECLARE #Char CHAR(1)
DECLARE #PrevChar CHAR(1)
DECLARE #WordCount INT
DECLARE #CharCount INT
SET #Index = 1
SET #WordCount = 0
WHILE #Index <= LEN(#InputString)
BEGIN
SET #Char = SUBSTRING(#InputString, #Index, 1)
SET #CharCount = #CharCount + 1
SET #PrevChar = CASE WHEN #Index = 1 THEN ' '
ELSE SUBSTRING(#InputString, #Index - 1, 1)
END
IF #PrevChar = ' '
SET #CharCount = 1
END
IF #Char = ' ' AND #CharCount < 3 AND #CharCount > 1
SET #WordCount = #WordCount + 1
SET #Index = #Index + 1
END
RETURN #WordCount
END
Now I have not tested it so you have to test it on your own but it should work. It will return all 2 letter words in the selected string. To get the 3 letters words just change
IF #Char = ' ' AND #CharCount < 4 AND #CharCount > 2
I hope this helps.
I have a userid table
UserId
JHOSMI
KALVIE
etc...
What I would like to do is create a select statement and pass user id, if the userid already exists then append 1 to the id, This gets complicated if you already have JHOSMI, JHOSMI1, then I want to return JHOSMI2.
Really appreciate help here.
Thanks in advance
edited 21-Jul
this is what i got so far.. but not working the way
select #p AS StaffID,
#old_p := #p,
#Cnt := #Cnt+1 As Lvl,
(SELECT #p :=Concat(#i, #Cnt)
FROM departmenttaff
WHERE upper(trim(UserId)) = upper(trim(StaffID))
AND upper(trim(department)) like upper(trim('SERVICE'))
) AS dummy
FROM (
SELECT
#i := upper(trim('JOHSMI')),
#p := upper(trim('JOHSMI')),
#old_p :='',
#Cnt:=0
) vars,
departmenttaff p
WHERE #p <> #old_p
order by Lvl Desc LIMIT 1;
This will do exactly what you want. You will need a unique constraint on your column.
You might also need to add in error code if success = 0.
This is in MSSQL, you will need to add the relevant commands for MySQL. I do not have MySQL so I cannot test it.
NOTE: You can replace the try catch with some IF EXISTS logic. I just prefer the try catch because its more stable for multiple threads.
begin tran
select * from #tmp
declare #success bit
declare #name varchar(50)
declare #newname varchar(50)
declare #nextid int
declare #attempts int
set #name = 'brad2something'
set #success = 0
set #attempts = 0
while #success = 0 and #attempts < 5 begin
begin try
set #attempts = #attempts + 1 -- failsafe
set #newname = #name
if exists (select * from #tmp where username = #name) begin
select #nextid = isnull(max(convert(int, substring(username, LEN(#name) + 1, 50))), 0) + 1
from #tmp where username like #name + '%' and isnumeric(substring(username, LEN(#name) + 1, 50)) = 1
set #newname = #name + CONVERT(varchar(20), #nextid)
end
insert into #tmp (username) values (#newname)
set #success = 1
end try begin catch end catch
end
--insert into #tmp (username)
--select
select #success
select * from #tmp
rollback
/*
drop table #tmp
create table #tmp (
username varchar(50) not null unique
)
insert into #tmp (username)
select 'brad'
union all select 'brad1'
union all select 'brad2something5'
union all select 'brad2'
union all select 'laney'
union all select 'laney500'
*/
I noticed you want to back fill data. If you want to back fill then this will work. It is extremely inefficient but there is no way around it. There is optimizing code you can put in for when an "error" occurs to prevent all previous counts from happening, but this will work.
begin tran
select * from #tmp
declare #success bit
declare #name varchar(50)
declare #newname varchar(50)
declare #nextid int
declare #attempts int
set #name = 'laney'
set #success = 0
set #attempts = 0
set #nextid = 1
while #success = 0 and #attempts < 5 begin
begin try
if exists (select * from #tmp where username = #name) begin
set #newname = #name + CONVERT(varchar(20), #nextid)
while exists (select * from #tmp where username = #newname) begin
set #nextid = #nextid + 1
set #newname = #name + CONVERT(varchar(20), #nextid)
end
end else
set #newname = #name
set #attempts = #attempts + 1 -- failsafe
insert into #tmp (username) values (#newname)
set #success = 1
end try begin catch end catch
end
--insert into #tmp (username)
--select
select #success
select * from #tmp
rollback
/*
drop table #tmp
create table #tmp (
username varchar(50) not null unique
)
insert into #tmp (username)
select 'brad'
union all select 'brad1'
union all select 'brad2something5'
union all select 'brad2'
union all select 'laney'
union all select 'laney500'
*/
Is it mandatory to have the count in same column? its better to have it in a different integer column. Anyways, if this is the requirement then select userid from table where userid like 'JHOSMI%', then do extract the number using mysql substr function.
For other people who might find this, here's a version in PostgreSQL:
create or replace function uniquify_username(varchar) returns varchar as $$
select $1 || coalesce((max(num) + 1)::varchar, '')
from
(select
substring(name, '^(.*?)[0-9]*$') as prefix,
coalesce(substring(name, '.*([0-9]+)$'), '0')::integer as num
from user1) users
where prefix = $1
$$ LANGUAGE sql;
I think it could be adapted to MySQL (though probably not as a stored procedure) but I don't have a MySQL server handy to do the conversion on.
Put a UNIQUE constraint on the column.
You didn't say what language you are using, so use this pseudo code
counter = 0
finished = false
while finished = false
{
try
{
if counter >= 1 then name = name + counter
counter = counter + 1
insert into table (name)
}
}
This code is extremely finicky. But will get the job done and there is no real other way to do this except for in sql, and you will always have some type of try catch to avoid two processes running at the same time. This way you use the unique key constraint to force the error, and supress it because it is expected.
I in no way condone using try/catch for business logic like this, but you are putting yourself in a situation thats unavoidable. I would say put the ID in a seperate column and make a unique constraint on both fields.
Proper solution:
Columns: Name, ID, Display Name
Unique constraint on: Name, ID
Display Name is a computed column (virtual) is Name + ID
If you do it this way, then all you have to do is INSERT INTO table (name, (select max() from table))