How to create column values by looking at other columns in a table? SQL - sql

I have three columns in a table.
Requirements: The value of col2 and col3 should make col1.
Below shows the table I have right now, which needs to be change.
col1 col2 col3
AB football
AB football
ER driving
ER driving
TR city
TR city
Below shows the table that needs to be change to
col1 col2 col3
AB_football_1 AB football
AB_football_2 AB football
ER_driving_1 ER driving
ER_driving_2 ER driving
TR_city_1 TR city
TR_city_2 TR city
As you can see in col1, it should take col2, put (underscore), then col3, put (underscore) then increment the number according to the values in col2 and col3.
Can this be approached within CREATE or SELECT or INSERT statement or Trigger Statement, if so any tips would be grateful.

Try as
SELECT col2
||'_'
||col3
||'_'
||rank col1,
col2,
col3
FROM (SELECT col2,
col3,
ROW_NUMBER()
OVER(
PARTITION BY col2, col3
ORDER BY col2) rank
FROM my_table)
Output
+---------------+------+----------+
| COL1 | COL2 | COL3 |
+---------------+------+----------+
| AB_football_1 | AB | football |
| AB_football_2 | AB | football |
| ER_driving _1 | ER | driving |
| ER_driving _2 | ER | driving |
| TR_city _1 | TR | city |
| TR_city _2 | TR | city |
+---------------+------+----------+

/* table is */
col1 col2 col3
test 123
/* Try this query */
UPDATE `demo`
SET `col1` = concat(col2, '_', col3)
/* Output will be */
col1 col2 col3
test_123 test 123

This is easy to do (at SELECT) using row_number() window function , something like this:
select
col2 ||'_'|| col3 ||'_'|| row_number() over(partition by col2, col3 order by col2) as col1,
col2,
col3
from t

Related

Scatter multiple rows having duplicate columns to single unique row in postgresql

how to scatter multiple duplicate rows into one row in sql/postgresql.
For example --->
lets i am getting 3 rows of
col1 col2 col3
-------------------
11 test rat
11 test cat
11 test test
I want something like this
col1 col2 col3 col4
------------------------
11 test rat cat
Its the same thing like groupby in lodash. But how do I achieve the same in postgresql query?
You're looking for crosstab
postgres=# create table ab (col1 text, col2 text, col3 text);
CREATE TABLE
postgres=# insert into ab values ('t1','test','cat'),('t1','test','rat'),('t1','test','test');
INSERT 0 3
postgres=# select * from crosstab('select col1,col2,col3 from ab') as (col1 text, col2 text, col3 text, col4 text);
col1 | col2 | col3 | col4
------+------+------+------
t1 | cat | rat | test
(1 row)
Disclosure: I work for EnterpriseDB (EDB)

Combining data from different rows into one

I have a database that looks something like this:
col1 | col2 | col3 | col4
User1 | Coms | Start | 19 June 2019
User1 | Coms | Ended | 20 June 2019
I would like to transpose the data into a single row, like this:
col1 | col2 | col3 | col4 | col5 (end status)
User1 | Coms | Start | 19 June 2019 | Ended
You see, this user Ended the session, meaning the second row of that transaction is pulled into the first row. If they did not end, the new End Status column will simply be a Null.
I know there is a function Stuff ... For XML Path query that can put some rows together into one comma delimited field, but this is not what I am looking for.
Any good ideas?
use conditional aggregation
select col1,col2,
max(case when col3='start' then col3 end),
max(case when col3='end' then col3 end),min(col4)
from table group by col1,col2
use conditional aggregation
select col1, col2,
max(case when col3='Start' then col3 end) as col3,
max(case when col3='Start' then col4 end) as col4,
max(case when col3='Ended' then 'Ended' end) as col5
from tablename
group by col1,col2

PSQL select either a or b in order but not both a and b if both a and b exists

I have a PSQL table
+--------+------+------+------+
| Col1 | Col2 | Col3 | Col4 |
+--------+------+------+------+
| 001 | 00A | 00B | 001 |
| 001001 | 00A | 00B | 001 |
| 002 | 00X | 00Y | 002 |
| 002002 | 00X | 00Y | 002 |
+--------+------+------+------+
I have the following PSQL query:
select *
from my_table
where (Col1 = '001' or Col4 = '001')
and Col2 = '00A'
order by Col3 asc;
I get the first two rows.
Here what happens is that it matches both conditions for OR condition. I need to match only one of the or conditions. That is if first condition (Col1='001001') is true then do not evaluate the next condition.
I need to select only the 2nd row (| 001001 | 00A | 00B | 001 |)
I have build another query using EXCEPT
select *
from my_table
where (Col1 = '001' or Col4 = '001')
and Col2 = '00A'
except (select *
from my_table
where Col1 != '001'
and Col2 = '00A')
order by Col3 asc
limit 1;
I would like to know if there is any other elegant queries for this job?
Your explanation is confusing as you say col1 = '001001' in one place and use 001 in the query. But I presume you want to use a hierarchy of comparison and return the one with the highest per each group ( col2,col3,col4) . Use DISTINCT ON. Change the condition in whichever way you like to return the appropriate row.
SELECT DISTINCT ON (col2, col3, col4) *
FROM my_table WHERE col2 = '00A'
ORDER BY col2,
col3,
col4,
CASE
WHEN col1 = '001001' THEN 1
WHEN col4 = '001' THEN 2
END;
DEMO
Does this give you what you want?
select *
from my_table
where (Col1 = '001' and Col2 != '00A')
or ((Col1 is null or Col1 = '') and Col4 = '001' and Col2 = '00A')
order by Col3 asc;

How can I import one column in a table to another table on sql?

I have the table
| Col1 | Col2 | Col3 |
I want a new table with these values
| Col4 | Col5 | Col2 | Col6 |
With any values of col2 onto the new table
Thanks!
If It Is Just About To Import All Data Of Col2 In Another Table ,Then
Suppose TB1 has Columns (Col1 , Col2 , Col3)
and TB2 has Columns (Col4 , Col5 , Col2 , Col6)
Then Your Quert Would Be Like This ,
Insert INTO TB2(Col2)(Select Col2 From TB1);
else
Please Give More Specification Like You Want To Update Data That is Not In TB2 Like That.

SQL Multiple rows into one row

My Table data looks like
Col1 | Col2 | Col3
1 | NULL | NULL
NULL | 2 | NULL
NULL | NULL | 3
It is given that for any column there will be only entry. This means that, in the above data, if row1 has value for Col1, then there will be no row with value for Col1. Similarly, if row1 has value for Col1, it will not have value for any other column.
I want to write a query, so that I get only one row out for entire data (leaving NULL values). ie.
Col1 | Col2 | Col3
1 | 2 | 3
The easiest way to do this is using aggregation:
select max(col1) as col1, max(col2) as col2, max(col3) as col3
from t;
select
sum(ifnull(col1,0)) as col1,
sum(ifnull(col2,0)) as col2
sum(ifnull(col3,0)) as col3
from t;
Assuming the table is called tab the following query will work if there are only 3 columns:
select t1.Col1, t2.Col2, t3.Col3
from tab t1, tab t2, tab t3
where t1.Col1 is not null and t2.Col2 is not null and t3.Col3 is not null
The problem is the query will have to alias the table for each additional column. It may not be perfect, but it is a solution.