SQL. Set column Value from a choice of other columns - mysql

Not sure if what I want to do is possible or not, and if it is I've hit a brick wall in my head of how to do it and searching hasn't found the answer.
I have a Column, we'll call it column A. This is currently blank and I want to populate it with the value from either column B or column C (which is randomly chosen).
In essence what I want to do, but which doesn't work is:
update MyTable
set Column A = Column B OR Column C
From MyTable
Any help would be greatly appreciated!

You can use case. If you want random, then:
update MyTable
set Column_A = (case when rand() < 0.5 then Column_B else Column_C end);
The above randomly assigns either column for each row. If you want all column_As to be either from B or C, but randomly chosen, I think I would use a similar technique:
update MyTable cross join
(select #r := rand()) params
set Column_A = (case when #r < 0.5 then Column_B else Column_C end);

Related

How to easily get row number when using LIMIT in MySQL?

Suppose I have a database table with quite a few rows which I want to display to an user. It would make sense to LIMIT the output, and make pages of rows. In MySQL I would do this:
SELECT * FROM myTable ORDER BY myValue LIMIT 120,10
which will show 10 rows starting from row 120. So MySQL must use, internally, some kind of order, and has numbered the rows accordingly. I would like to display the row number with each row. How do I get access to these numbers, using only MySQL? To be clear, I am looking for something like this:
SELECT *,<LIMIT_ROWNO> FROM myTable ORDER BY myValue LIMIT 120,10
I looked online and in the manual, but I cannot find it. I would prefer something simple, without using variables, or functions. Isn't there a predefined expression for this?
I can solve this problem easily in PHP, but it would be more logical to get the row numbers from MySQL.
You can't do it without using variables, e.g.:
SELECT m.*, #rownum := #rownum + 1 as `num`
FROM myTable m, (SELECT #rownum := 120) a
ORDER BY myValue LIMIT 120,10;
set #rownum=120;
SELECT *,#rownum:=#rownum+1 as rn FROM myTable ORDER BY myValue LIMIT 120,10;
as of final of 2021, why not:
SELECT
t1.*,
COUNT(t1.*) OVER (PARTITION BY RowCounter) as TotalRecords
FROM (
SELECT a, b, c, 1 as RowCounter
FROM MyTable
) t1
LIMIT 120,10
using a subquery with a column marking every row with the same value, will give us the possibility to count all of the same values of the the resulted column with PARTITION BY window function's group

Do i use count(*) to count record or i add count column into my table directly

My team lead insisting me to add days entry count column within table and update it regularly. something like this
Get previous record
take count column value
Add .5 into that value
And update the count record in current record
like this
.5
1
1.5
2 //each time i have to get previous value to make new value which means select statment, then update statement
While I think that this is not the right way. I can count [using Count(*)] the record to display days which is easy why i bother to add it, use update command to know previous entry etc. The reason he told that we can get count directly without query bunch of records which is performance wise is fast. How you do this? what is correct way?
If I understand correctly, you just want row_number() divided by 2:
select t.*,
(row_number() over (order by ??) ) / 2.0
from t;
The ?? is for whatever column specifies the ordering of the table that you want.
UPDATE YourTable
SET COUNT_COLUMN = (SELECT MAX(COUNT_COLUMN) + 0.5
FROM YourTable
)
WHERE "Your condition for the current record";
For better performance add index on to COUNT_COLUMN column of YourTable.
Hi Fizan,
You can achieve this using function. You can create a function to get resultant value and update it in you column. Like this -
CREATE function Get_Value_ToBeUpdated
RETURN DECIMAL(10,2)
AS
BEGIN
DECLARE result decimal (10,2);
DECLARE previousValue decimal (10,2);
DECLARE totalCount int;
SELECT previousValue = SELECT MAX(columnName) FROM YourTable order by primaryColumn desc
SELECT totalCount = SELECT COUNT(1) FROM YourTable
SET result = ISNULL(previousValue,0) + ISNULL(totalCount,0)
RETURN result;
END
UPDATE YourTable SET COLUMNNAME = DBO.Get_Value_ToBeUpdated() WHERE Your condition
Thanks :)

Mysql how to sum column with previous column sum

In XLS I have two columns A and B.
A,B
1,1
2,3
2,5
1,6
5,11
2,13
A column have value, and B column is calculated with formula, (A + (previous row B value))
How can i do this calculation on MYSQL?
I'm trying to join same table twice and i can get previous rows A column next to B.
I can sum them, but how can I sum them with this formula?
XLS formula looks like this:
H20 = H19+G20
This is my SQL created from suggestions.
SELECT
date, time, sum, #b := sum+#b as 'AccSum', count
FROM
(SELECT
t.date, t.time, t.sum, t.count
FROM TMP_DATA_CALC t
ORDER BY t.epoch) as tb
CROSS JOIN
(SELECT #b := 0) AS var
;
SELECT A, #b := A+#b AS B
FROM (SELECT A
FROM YourTable
ORDER BY id) AS t
CROSS JOIN
(SELECT #b := 0) AS var
The user variable #b holds the value of B from the previous row, allowing you to add the current row's A to it.
DEMO
http://sqlfiddle.com/#!2/74488/2/1 shows how to select the data.
SET #runtot:=0;
Select a,b, #runtot:=#runtot+a from b
However there's an underlying problem I can't figure out. Since you don't have a defined order, the SQL could do this ordering in any way, so you may not get the desired results.. without a defined order you results may be unpredictable.
runtot = running total.
In MySQL we don't have any function like partition by which Oracle has. You can use curser to achieve your requirement. Or we can write any function which will get rownumber as input then add these two values then return that to query.
select b from xsl limit rownum-1,1 + select a from xsl limit rownum,1

Row number in mySQL

Is it possible to get the row number in MySQL? Say I have a 'table'
ID tag name
1 A alpha
4 B beta
5 C gamma
8 D ceta
How can I get in MySQL that, for example, 'C' is the 3rd row in that table? Following:
SET #pos=0;
SELECT #pos:=#pos+1,tag FROM table ORDER BY tag ASC;
counts the rows as it should. But (sorry for ignorant code)
SET #pos=0;
SELECT #pos:=#pos+1,tag FROM table where tag='C' ORDER BY tag ASC;
gives 1 row as a result, with pos as 0, as it probably should.
Is there a way to get the 'pos' to be '3' as I need it to be?
(Ordering would be important as well, whether it is relevant to the question or not..)
You can use this
Select rownum from (
SELECT #rownum:=#rownum+1 rownum, t.*FROM (SELECT #rownum:=0) r, table t order by tag) as t1
where tag = 'C'
In case your IDs are strictly increasing with row numbers, you can do
SELECT COUNT(*) FROM tbl WHERE ID <= (SELECT ID FROM tbl WHERE tag = 'C');
I am not sure what you mean by the ordering though.
Side note: Your code
SET #pos=0;
SELECT #pos:=#pos+1,tag FROM tbl where tag='C' ORDER BY tag ASC;
cant work, because here #pos operates on the result set only, which consists of only one record.
Actually, there's one possibility that I didn't consider before:
SELECT count(1) FROM table WHERE tag <= 'C' ORDER BY tag
This seems to do the same thing, and a bit faster, too.. Or am I missing something?

In mysql, can I count how many rows satisfy some condition, if not then exit the count?

Basically I store data in MySql 5.5. I use qt to connect to mysql. I want to compare two columns, if col1 is greater than col2, the count continues, but when col1 is less than col2, count finishes and exits. So this is to count how many rows under some condition at the beginning of column. Is it possible in mysql?
An example:
Col1 Col2
2 1
2 3
2 1
The count I need should return 1, because the first row meets the condition of Col1 > Col2, but the second row doesn't. Whenever the condition is not meet, counting exits no matter if following rows meet the condition or not.
SELECT COUNT(*)
FROM table
WHERE col1 > col2
It's a little difficult to understand what you're after, but COUNT(*) will return the number of rows matched by your condition, if that's your desire. If it's not, can you maybe be more specific or show example(s) of what you're going for? I will do my best to correct my answer depending on additional details.
You should not be using SQL for this; any answer you get will be chock full of comprimise and if (for example) the result set from your intial query comes back in a different order (due to an index being created or changed), then they will fail.
SQL is designed for "set based" logic - and you really are after procedural logic. If you have to do this, then
1) Use a cursor
2) Use an order by statement
3) Cross fingers
This is a bit ugly, but will do the job. It'll need adjusting depending on any ORDER etc you would like to apply to someTable but the principle is sound.
SELECT COUNT(*)
FROM (
SELECT
#multiplier:=#multiplier*IF(t.`col1`<t.`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1
) scanQuery
The #multiplier variable will keep multiplying itself by 1. When it encounters a row where col1 < col2 it multiplies by 0. It will then continue multiplying 0 x 1. The outer query then just sums them up.
It's not ideal, but would suffice. This could be expanded to allow you to get those rows before the break by doing the following
SELECT
`someTable`.*
FROM `someTable`
INNER JOIN (
SELECT
`someTable`.`PrimaryKeyField`
#multiplier:=#multiplier*IF(`col1`<`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1
) t
ON scanQuery.`PrimaryKeyField` = `someTable`.`PrimaryKeyField`
Or possibly simply
SELECT
`someTable`.*
#multiplier:=#multiplier*IF(`col1`<`col2`,0,1) AS counter
FROM `someTable` t, (SELECT #multiplier := 1) v
HAVING counter = 1