CREATE TABLE example (
id integer,
name text
);
SELECT COUNT(*) FROM example;
>> 10
SELECT * FROM example;
...>
id name
-- --------
1
2
3
4
5
6
7
8
9
10
if there is a table like the code-block over, and no values in the column "name" as you can see.
I want to update all the values of the column like (A, B, C, D, E, F, G, H, I, J)
But, it is so inefficient to write this codes.
UPDATE example SET name = "A" where id = 1,
UPDATE example SET name = "B" where id = 2,
.
.
.
UPDATE example SET name = "J" where id = 10,
Is there some way to run these codes in a code like loop or something?
We can use the CHAR() ASCII function here:
UPDATE example
SET name = CHAR(64 + id);
Note that 65 is the ASCII character code for A. Once your id column exceeds the number of uppercase alphabets, my answer will start assigning characters which are not uppercase letters. But your question also does not mention what the additional behavior should be.
Related
I work with QGIS and PostgreSQL with PostGIS. I need help with dynamic queries for PostgreSQL.
Information is structured in tables that contain votes for parties, and other types of information like geographic area or election date.
Some columns contains values that have to be splitted among several parties. For example, we can have a column with name "PartyA_PartyB" and a value of 10, and it should be splitted 5 votes to PartyA and 5 votes to PartyB. Additionally we will have independent columns for PartyA and PartyB (separated), so we need to compute a column where we allocate the original PartyA + PartyA_PartyB/2.
So for example for the given the tables “Election Results” and "Parties":
create table election_results ("Country" text, "PartyA" text, "PartyB" text, "PartyC" text, "PartyA_PartyB" text);
insert into election_results
VALUES
('Argentina', 100, 10, 20, 2),
('Uruguay', 3, 5, 1, 0),
('Chile', 40, 200, 50, 10)
;
create table parties (party text);
insert into parties
VALUES
('PartyA'),
('PartyB'),
('PartyC'),
('PartyD'),
('PartyE')
;
I need to create a new table with a column where 'new' PartyA = PartyA + PartyA_PartyB/2 and 'new' PartyB = PartyB + PartyA_PartyB/2
So with previous data desired result is:
Country
PartyA
PartyB
PartyC
Argentina
101
11
20
Uruguay
3
5
1
Chile
45
205
50
In all cases the special characters that separates the names to be splitted is '_'.
We can have n parties in the column names (for example PartyA_PartyB_PartyD_PartyE). Votes have to be splitted among the n parties.
With my limited understanding I think iterate over the columns could be a solution, look for the '_' character and recalculate.
Note: Please store your values not as text but as a numeric type.
demo: db<>fiddle (2 joined colums)
demo: db<>fiddle (additional 3 joined columns)
Create your new table:
CREATE TABLE parties (
"Country" text,
"PartyA" numeric,
"PartyB" numeric,
"PartyC" numeric
);
Copy values for the "single" columns:
INSERT INTO parties
SELECT "Country", "PartyA", "PartyB", "PartyC"
FROM election_results;
Update the columns with a function
SELECT * FROM split_and_update_parties();
The function could look like this:
CREATE OR REPLACE FUNCTION split_and_update_parties()
RETURNS void
LANGUAGE plpgsql AS
$func$
DECLARE
i record;
j text;
n integer;
BEGIN
FOR i in
SELECT
column_name, -- 1
string_to_array(column_name, '_') -- 2
FROM information_schema.columns
WHERE table_name = 'election_results'
AND column_name ~ 'Party'
LOOP
n = cardinality(i.string_to_array); -- 3
IF n > 1 THEN
FOREACH j in array i.string_to_array LOOP
EXECUTE format('
UPDATE parties p -- 4
SET %I = p.%I + s.val / %s
FROM (
SELECT %I as val, "Country"
FROM election_results
) s
WHERE p."Country" = s."Country"
', j, j, n, i.column_name);
END LOOP;
END IF;
END LOOP;
END
$func$;
Explanation:
Fetch column names from internal information schema
Immediately split the names and convert them into arrays
Count the elements of the arrays to know the divider needed furtherly in the calculation
Loop through all these multiple-party-arrays/columns (with more than 1 element), fetch the original values from the election_results table and update the single-party-columns in the new table
This question already has answers here:
Simple Postgresql Statement - column name does not exists
(2 answers)
Fixing column "columnname" does not exist pgsql in database. Double quote vs single quote error
(1 answer)
postgres column "X" does not exist
(1 answer)
Closed 1 year ago.
I'd like to write postgresql code that defines a table B based on table A values, according to A field of string type named d, if it matches any element of predefined string lists.
Table A contains 2 fields: c and d, d is a string.
Here is what I've wrote:
create table B as select c, CASE when d in ("A1", "A2", "A3") then 1 end as TYPE1, CASE when d in ("B1", "B2", "B3") then 1 end as TYPE2 from A;
I'd like TYPE1 field to be set to 1 if d is any value among "A1",
"A2","A3" and TYPE2 field to be set to 1 if d is any value among "B1","B2",B3".
Here's the error I get:
column "A1" does not exist.
In the code that I will finally write the string values for which TYPE1 or TYPE2 are to be set to 1, cannot be simply described by a matching pattern as in this snippet
Thanks for your help
String literals are enclosed with ':
create table B as select c, CASE when d in ('A1', 'A2', 'A3') then 1 end as TYPE1, CASE when d in ('B1', 'B2', 'B3') then 1 end as TYPE2 from A;
It works just changing '"' surrounding strings "A1", "A2" ... by single quotes 'A1', 'A2' , 'A3'
I have a ID field that is 11 chars long 123456789abc
How can I check the length
how can I check position 3 to ensure it's numeric
Select * from table
where ID = position 2 must be 'A-Z'
You can use like with patterns. Something like this:
Select *
from table
where id like '___[0-9]%' and len(id) = #length
How can I select records where in the column Value the 5th character is letter A?
For example the following records:
ID Value
-------------------------
1 1234A5636A6363
2 1234A4343B6363
3 1234B5353A6363
if I run
select * from table
where Value like '%A%'
this will return all records
but all I want is the first 2 where the 5th character is A, regardless if there are more A characters in the text or not
select *
from your_table
where substring(Value, 5, 1) = 'A'
The LIKE operator, in addition to %, which matches any number of any character, can use _, which matches any one single character. You may try:
SELECT *
FROM yourTable
WHERE Value LIKE '____A%'; -- 4 underscores here
use like below by using _(underscore)
LIKE '____A%'
SQL Server
select *
from YourTableName
where CHARINDEX('A', ColumnName) = 5
Note:- This finds where string 'A' starts at position 5
AND specify Your ColumnName
Although I saw update statements to update field based on existing values, I could not find anything similar to this scenario:
Suppose you have a table with only one column of number(4) type. The value in the first record is 1010.
create table stab(
nmbr number(4)
);
insert into stab values(1010);
For each digit
When the digit is 1 -- add 3 to the digit
When the digit is 0 -- add four to the digit
end
This operations needs to be completed in a single statement without using pl/sql.
I think substr function need to be used but don't know how to go about completing this.
Thanks in advance.
SELECT DECODE(SUBSTR(nmbr,1,1), '1', 1 + 3, '0', 0 + 4) AS Decoded_Nmbr
FROM stab
ORDER BY Decoded_Nmbr
Is that what you are after?
So, it seems you need to convert every 0 and 1 to a 4, and leave all the other digits alone. This seems like a string operation (and the reference to "digits" itself suggests the same thing). So, convert the number to a string, use the Oracle TRANSLATE function (see the documentation), and convert back to number.
update stab
set nmbr = to_number(translate(to_char(nmbr, '9999'), '01', '44'))
;
assuming its always a 4 digit #; you could use substring like below
-- postgres SQL example
SELECT CASE
WHEN a = 0 THEN a + 4
ELSE a + 3
end AS a,
CASE
WHEN b = 0 THEN b + 4
ELSE b + 3
end AS b,
CASE
WHEN c = 0 THEN c + 4
ELSE c + 3
end AS c,
CASE
WHEN d = 0 THEN d + 4
ELSE c + 3
end AS d
FROM ( SELECT Substr( '1010', 1, 1 ) :: INT AS a,
Substr( '1010', 2, 1 ) :: INT b,
Substr( '1010', 3, 1 ) :: INT c,
Substr( '1010', 4, 1 ) :: INT d )a
--- Other option may be (tried in postgreSQL :) ) to split the number using regexp_split_to_table into rows;then add individual each digit based on the case statement and then concat the digits back into a string
SELECT array_to_string ( array
(
select
case
WHEN val = 0 THEN val +4
ELSE val +3
END
FROM (
SELECT regexp_split_to_table ( '101010','' ) ::INT val
) a
) ,'' )
My answer to the interview question would have been that the DB design violates the rules of normalization (i.e. a bad design) and would not have this kind of "update anomaly" if it were properly designed. Having said that, it can easily be done with an expression using various combinations of single row functions combined with the required arithmetic operations.