How to compare and take non-duplicate text in Postgresql - postgresql

coalesce(case when main_parse_user.bio is distinct from EXCLUDED.bio
and EXCLUDED.bio is not null
then concat(trim(main_parse_user.bio), ' ', trim(EXCLUDED.bio))
else main_parse_user.bio end)
there is a code that takes and adds new data to an existing column
But I need to make sure that at first the code compares and enters only those words that are unique
EXAMPLE
db
ID NAME
1 qwerty
input
ID NAME
1 qwerty new
output
ID NAME
1 qwerty | new
you can do this in postgresql

Related

How to end up with a new Postgresql column value if there is a mismatch

INSERT INTO main_parse_user ("user_id","group_id", "username","bio", "first_name")
VALUES (%s,%s,%s,%s,%s) ON CONFLICT (user_id) DO UPDATE SET (group_id,username,bio,first_name) =
(EXCLUDED.group_id,EXCLUDED.username,
coalesce(main_parse_user.bio, EXCLUDED.bio),EXCLUDED.first_name)
Here is the code I have now, in case of a conflict, it updates everything except bio (if it is empty, it updates)
There was a new need to check with the old one when a new base arrives and, if the values ​​differ, to supplement, and if the values ​​do not differ, just leave it as it is
EXAMPLE
OLD
bio id
1 qwerty
NEW
bio id
1 qwerty1
AFTER
bio id
1 qwerty | 1
And if both bios in the old and new tables are the same, then do not touch
What you are getting is precisely does the coalesce() function does. Since the new requirement is to to supplement (I assume that means add to the existing value) you can replace, coalesce(...) with
case when main_parse_user.bio is distinct from EXCLUDED.bio
and EXCLUDED.bio is not null
then concat(trim(main_parse_user.bio), ' ', trim(EXCLUDED.bio))
else main_parse_user.bio
end

multiple form fields with the same path inserting to db in spring

I have to insert data to db in form fields that have the same path and i want to save it different id's but rather it concatenated it with ",", how could i possibly do it?
I tried to make some alias in SQL but it saves into same db field name with concatenated with ","
i expected in db when i insert that
EX.
db field name = description
input 1 value = "john";
input 2 value = "doe";
id description
1 john
2 doe
above is my expected result
but in my case when i insert it shows these
id description
1 john,doe
can someone help me to achieve that result ? THANKYOU!
Let me present a similar situation. You have a database of people and you are concerned that each person might have multiple phone numbers.
CREATE TABLE Persons (
person_id INT UNSIGNED AUTO_INCREMENT,
...
PRIMARY KEY(person_id) );
CREATE TABLE PhoneNumbers (
person_id INT UNSIGNED,
phone VARCHAR(20) CHARACTER SET ascii,
type ENUM('unknown', 'cell', 'home', 'work'),
PRIMARY KEY(person_id, phone) );
The table PhoneNumbers has a "many-to-1" relationship between phone numbers and persons. (It does not care if two persons share the same number.)
SELECT ...
GROUP CONCAT(pn.phone) AS phone_numbers,
...
FROM Persons AS p
LEFT JOIN PhoneNumbers AS pn USING(person_id)
...;
will deliver a commalist of phone numbers (eg: 123-456-7890,333-444-5555) for each person being selected. Because of the LEFT, it will deliver NULL in case a person has no associated phones.
To address your other question: It is not practical to split a commalist into the components.

replace substring for particular position in postgres

I have a table and want update query to update dob
------------
dob
------------
19101984
19111984
19071985
19081985
19101985
19121985
I want to remove sub string from position 5 to character length of 2 means in the result table will be :
------------
dob
------------
191084
191184
190785
190885
191085
191285
Use regex_replace:
select regexp_replace(dob::text, '(\d{4})\d{2}(\d{2})', E'\\1\\2')
from your_table;
For updating:
update your_table
set dob = regexp_replace(dob, '(\d{4})\d{2}(\d{2})', E'\\1\\2');
The regex pattern being used here is:
(\d{4})\d{2}(\d{2})
^^^^ ^^^^ <-- capture groups
The first four and last two digits are captured in groups 1 and 2, respectively. Then, we simply replace with the first and second capture group.
It is not clear whether the dob column is text or not. If it is numeric, then you should be able to cast to text and run the above query.
Demo

How to fill a nullable integer column and convert it into a serial primary key in Postgresql?

My table contains an integer column (gid) which is nullable:
gid | value
-------------
0 |  a
| b
1 | c
2 | d
| e
Now I would like to change the gid column into a SERIAL primary key column. That means filling up the empty slots with new integers. The existing integers must remain in place. So the result should look like:
gid | value
-------------
0 |  a
3 | b
1 | c
2 | d
4 | e
I just can't figure out the right SQL command for doing the transformation. Code sample would be appreciated...
A serial is "just" a column that takes it default value from a sequence.
Assuming your table is named n1000 then the following will do what you want.
The first thing you need to do is to create that sequence:
create sequence n1000_gid_seq;
Then you need to make that the "default" for the column:
alter table n1000 alter column gid set default nextval('n1000_gid_seq');
To truly create a "serial" you also need to tell the sequence that it is associated with the column:
alter sequence n1000_gid_seq owned by n1000.gid;
Then you need to advance the sequence so that the next value doesn't collide with the existing values:
select setval('n1000_gid_seq', (select max(gid) from n1000), true);
And finally you need to update the missing values in the table:
update n1000
set gid = nextval('n1000_gid_seq')
where gid is null;
Once this is done, you can define the column as the PK:
alter table n1000
add constraint pk_n1000
primary key (gid);
And of course if you have turned off autocommit you need to commit all this.

Create view with fields from another table as column headers

I've got two tables that I'd like to combine into a view. The first table contains the structure:
Template Table
componentID | title
======================
1000 | blue
1001 | red
1002 | orange
The second table contains the actual data that will be stored, and the columns reference the ID of the first table:
Data Table
id | field1000 | field1001 | field1002
======================================
1 | navy | ruby | vermilion
2 | midnight | crimson | amber
What I'd like to get as a result in a view:
Combined Table/View?
id | blue | red | orange
=================================
1 | navy | ruby | vermilion
2 | midnight | crimson | amber
Is this possible? I've been trying to get it to work with pivot tables, but I'm getting hung up on how to use the titles as the columns for the data.
Ok, I went a bit overboard with this one but this will do what you want. This procedure will combine all fields with the proper data table columns, and does not need to know nor care how many columns there are in the data tables.
It does not use cursors, but due to the possibility of many template tables, it does use Dynamic SQL to generate the Select statement for the final return.
Only caveat is it's not a View, it's a stored procedure, because it allows to pass the variable for the data table you want to ultimately select from.
The assumptions:
The template table is static
There is one template table for all data tables
All fields in any data tables must be unique *
All data tables have a PK/identity field with the word 'id' in it that must be ignored
All fields in the data tables have a corresponding title in the template table
All fields in the data table are prefixed with the word 'field' and all of the reference ID's in the template table correspond to those field names with 'field' removed, based on your example
*- It can of course be improved by modifying the template table schema to also have a field for the data table that the field title belongs to, for example, which would remove this assumption #3.
The process:
First we need a mapping of the field names, reference IDs, and column titles. We do this with a table variable and get our info from syscolumns. Then, we update our temp table to get the titles from the TemplateTable table.
Then, we need to build a dynamic Select list from the DataTable (which is a parameter in the SP and therefore requires some dynamic SQL to execute). My preferred method of doing this is by having a bit column in my source table that I can update, something like 'IsCompleted', and then using a regular While loop to get through each row. Inside the While loop, all we do is grab the current "TitleReference" from our temporary table variable, and append to the select list the real field name from syscolumns (from first step above).
Finally, we execute the dynamic SQL statement which has a Select, and when this is inside a stored procedure that is executed, the result is returned as the result of the stored procedure.
The Full Working Code
Create Procedure usp_CombineTables
(
#DataTableName varchar(50)
)
As
-- Test
-- Exec usp_CombineTables 'DataTable'
-- Set up our variables
Declare #DataTableIdFieldName varchar(50), -- The ID field of the data table, dynamic
#IsCompleted bit, -- Used by While loop to know when to exit
#CurrentTitleReference int, -- Used in While loop as the ID from TemplateTable that relates to the real data field name and the desired title
#CurrentDataFieldName varchar(50), -- Used in While loop for the current actual field name in the data table
#CurrentTitle varchar(50), -- Used in While loop for the desired field name in the resulting table of the stored proc
#DynamicSelectQuery varchar(2000) -- Stores the SQL query that is dynamically built and executed for the final result; can increase value if needed
-- Use table variable to correlate the datatable columns, titles, and references
Declare #TitleReferences Table (
TitleReference int,
DataTableColumnName varchar(50),
Title varchar(50),
Completed bit default 0
)
-- Get the info from syscolumns about our datatable; assumes that all of the field names are prefixed with the word 'field' which needs to be removed
Insert Into #TitleReferences (
TitleReference,
DataTableColumnName
)
Select
Replace(name, 'field', '') As TitleReference,
name As DataTableColumnName
From syscolumns
Where id = OBJECT_ID(#DataTableName)
And name Not Like '%id%' -- assumes DataTable will always have a PK with 'id' in it, need to ignore/remove
-- Get the titles -- assumes only one template table for all data tables; all data fields accross tables must be unique
Update #TitleReferences
Set Title = t.Title From TemplateTable As t
Where TitleReference = t.ComponentID
-- Get the ID field of the data table
Set #DataTableIdFieldName = (
Select name From syscolumns
Where id = OBJECT_ID(#DataTableName)
And name Like '%id%')
-- Build a dynamic SQL query to select from the datatable with the right column names
Set #DynamicSelectQuery = 'Select ' + #DataTableIdFieldName + ', ' -- start with the ID
Set #IsCompleted = 0
While (#IsCompleted = 0)
Begin
-- Retrieve the field name and title from the current row based on title reference
Set #CurrentTitleReference = (Select Top 1 TitleReference From #TitleReferences Where Completed = 0)
Set #CurrentDataFieldName = (Select DataTableColumnName From #TitleReferences Where TitleReference = #CurrentTitleReference)
Set #CurrentTitle = (Select Title From #TitleReferences Where TitleReference = #CurrentTitleReference)
-- Append the next select field to the dynamic query
Set #DynamicSelectQuery = #DynamicSelectQuery +
#CurrentDataFieldName + ' As ' + QuoteName(#CurrentTitle)
-- Set up to move past current record in next iteration
Update #TitleReferences Set Completed = 1 Where TitleReference = #CurrentTitleReference
-- Exit loop or add comma for next field
If (Select Count(Completed) From #TitleReferences Where Completed = 0) = 0
Begin
Set #IsCompleted = 1
End
Else
Begin
-- Add comma to select field for next column
Set #DynamicSelectQuery = #DynamicSelectQuery + ','
End
End
-- Now the column list is built, just add the table and exec
Set #DynamicSelectQuery = #DynamicSelectQuery +
' From ' + #DataTableName
Exec(#DynamicSelectQuery)
The Result
Hope this helps, it was fun writing it!
something on these lines
DECLARE #f0 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1000)
DECLARE #f1 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1001)
DECLARE #f2 VARCHAR(50)=(SELECT title FROM template WHERE componentID=1002)
#sql='SELECT field1000 AS ' + quotename(#f0) + ' field1001 AS ' + quotename(#f1) + ' field1002 AS ' + quotename(#f2) + ' FROM data'
exec sp_executesql #sql