String aggregation in postgresql table using psycopg2 - postgresql

I have following table in Postgresql 11.0.
id code name1 name2
1 XXX abc sdf
1 XXX def null
2 ZZZ zut null
3 YYY gtj bzu
3 YYY null nuz
I would like to aggregate the values in name1 and name2 column for each id (in python). The below query runs perfectly in pgadmin but gives error through python script.
try:
cursor.execute("""
UPDATE tbl t1
SET name1 = sub_q.name1,
name2 = sub_q.name2
FROM
(
SELECT id, code, string_agg(name1, ' ; ') as name1, string_agg(name2, ' ; ') as name2
FROM tbl as t2
GROUP BY t2.id, t2.code
) AS sub_q
WHERE sub_q.id= t1.id
;
)
""")
except:
print ("The table cannot be created")
The expected output is:
id code name1 name2
1 XXX abc; def sdf
2 ZZZ zut null
3 YYY gtj bzu; nuz

Related

postgresql - unnest, for each result

I would like to create a view and I do some data handling for each result of unnest function.
In my column column2 I have :
"12345"
"123456"
"12345,123456" or more number
I would like to do some unnest(col2, ',') and for each result do something like this:
if length(col2) = 5 then treatment_1
else if length(col2) = 6 then treatment_2
Example in table:
col1 col2
-------------------
D1 12345, 123456
D3 12345
D4 123456
Expected Result into a view (with a treatment for each row in a col2) :
col1 col2
-------------------
D1 12345
D1 123456
D3 12345
D4 123456
You can use regexp_split_to_table to split the string into multiple rows:
select t1.col1
, case
when length(split.col2) > 5 then right(split.col2, 3)
else replace(split.col2, '123', '***')
end as col2
from Table1 t1
cross join
regexp_split_to_table(t1.col2, '\s*,\s*') split(col2)
Working example at SQL Fiddle.

sql script to export table's column data to another table's column

Let's say , I have two table with same schema but different data .
Table_A and Table_B .
Table_A
--------
ID(p_key) Number(p_key) Column3 Column4
-----------------------------------------------------
ID1 1 AAA BBB
ID1 2 CCC DDD
ID2 1 EEE FFF
ID2 2 GGG HHH
-
Table_B
--------
ID(p_key) Number(p_key) Column3 Column4
-----------------------------------------------------
ID1 1 AAA_1 BBB_1
ID1 2 CCC_1 DDD_1
ID2 1 EEE_1 FFF_1
ID2 2 GGG_1 HHH_1
I want to export(overwrite) Table_B column3 data to Table_A column3 , where ID and Number Columns data are equal .
After executing of script , Table_A's data should be ,
Table_A
--------
ID(p_key) Number(p_key) Column3 Column4
-----------------------------------------------------
ID1 1 AAA_1 BBB
ID1 2 CCC_1 DDD
ID2 1 EEE_1 FFF
ID2 2 GGG_1 HHH
How can I make this using sql script only ?
I use MS SQL-Server 2008 R2 .
UPDATE TBLA
SET TBLA.Column3=TBLB.Column3 --, TBLA.Column4=TBLB.Column4 if you want
FROM
Table_A AS TBLA
LEFT OUTER JOIN Table_B AS TBLB ON (TBLB.ID1 = TBLA.ID1 AND TBLB.ID2 = TBLA.ID2)
Please note that 'ID' columns (i.e. 'primary keys') must be unique (as pkeys are :).But to be sure -as I don't know your exact table structure- before you execute the code above, create a SELECT statement with the join(s) and if the result set is correct, then add it to the UPDATE.

Merge multiple queries excluding common results

Data :
--Table 1 :
Id ZoneName
----------- --------
20011 Name1
10027 Name1
20011 Name1
20011 Name1
20011 Name1
20074 Name1
20011 Name2
20011 Name2
10059 Name3
20011 Name2
Query :
Select Top 2 [Id] From Table1 -- First Query
WHERE ZoneName = 'Name1'
UNION
SELECT Top 1 [Id] from Table1 -- Second Query
WHERE ZoneName = 'Name1'
UNION
SELECT Top 1 [Id] from Table1 -- Third Query
WHERE ZoneName = 'Name1'
Result :
Id
-----
20011
Expected Result :
20011
10027
20074
From the above query I need 3 results from each query that do NOT overlap each other, in this case the expected result should contain the top 2 for query 1 i.e. 20011 and 10027 and for the next top 1 it should exclude those 2 results and return 20074 for query 2.
Note : I have used a single WHERE condition for this example, however in the actual query each of the query has different Where conditions, and could end up having same / different result from the query above itself.
As far as I know If you are searching to query distinct Id's for a particular ZoneName then this may work out
SELECT DISTINCT ID
FROM TABLE1
WHERE ZoneName="Name1"

Pivot table and combine records onto 1 line

I've tried many different ways to pivot a table to show all records on 1 row. I've provided my query for the closest solution I came up with. It'll probably be easier if I illustrate what I need. Since there can be an unlimited number of teacher survey questions the query has to be dynamic. I've modified the column names to make it easier to read.
teacherSurveyQuestions
TSQID CID Order OQReference Stem
1 1011 1 q1_rb blabla
2 1011 2 q2_rb blabla
3 1011 3 q2a_cb blabla
teacherSurveyUserID
TSUID firstName lastName UID
1 Bob Smith 1027
2 Tom Jones 1034
teacherSurveyAnswers
TSAID UID TSQID TSUID Response
1 1027 1 1 Bob 1
2 1027 2 1 Bob 2
3 1027 3 1 Bob 3
4 1034 1 2 Tom 1
5 1034 2 2 Tom 2
6 1034 3 2 Tom 3
Now I need this data to look like this:
firstName lastName q1_rb q2_rb q2a_cb
Bob Smith Bob 1 Bob 2 Bob 3
Tom Jones Tom 1 Tom 2 Tom 3
Here's what I have so far that kind of works except all the responses are NULL
declare #query as nvarchar(max),
#colsPivot as nvarchar(max)
select #colsPivot = stuff((select ','
+ quotename(OQReference)
from teacherSurveyQuestions tsq
where tsq.CID = 1011
order by tsq.Order
for xml path(''), type
).value('.', 'nvarchar(max)')
,1,1,'')
set #query
= 'select *
from
(
select firstName, lastName, value, col +''_''+ CAST(rn as varchar(10)) as col
from
(
select
tsu.TSUID
,tsu.firstName
,tsu.lastName
,tsq.OQReference
,tsa.Response
,ROW_NUMBER() over(partition by tsu.TSUID order by tsq.Order) rn
from teacherSurveyQuestions tsq
inner join teacherSurveyAnswers tsa on tsa.TSQID = tsq.TSQID
inner join teacherSurveyUsers tsu on tsu.TSUID = tsa.TSUID
where tsq.CID = 1011
) x
unpivot
(
value
for col in (OQReference)
) u
) x1
pivot
(
max(value)
for col in ('+ #colspivot +')
) p'
exec(#query)
Result of query:
firstName lastName q1_rb q2_rb q2a_cb
Bob Smith NULL NULL NULL
Tom JOnes NULL NULL NULL
Try this
declare #query as nvarchar(max),
#colsPivot as nvarchar(max)
select #colsPivot = stuff((select ','
+ quotename(OQReference)
from teacherSurveyQuestions tsq
where tsq.CID = 1011
order by tsq.[Order]
for xml path(''), type
).value('.', 'nvarchar(max)')
,1,1,'')
set #query
= 'select firstName, lastName,'+ #colspivot +'
from
(
select firstName, lastName,Response, value
from
(
select
tsu.TSUID
,tsu.firstName
,tsu.lastName
,tsq.OQReference
,tsa.Response
,ROW_NUMBER() over(partition by tsu.TSUID order by tsq.[Order]) rn
from teacherSurveyQuestions tsq
inner join teacherSurveyAnswers tsa on tsa.TSQID = tsq.TSQID
inner join teacherSurveyUserID tsu on tsu.TSUID = tsa.TSUID
where tsq.CID = 1011
) x
unpivot
(
value
for col in (OQReference)
) u
) x1
pivot
(
max(Response)
for value in ('+ #colspivot +')
) p'
exec(#query)
SQL FIDDLE DEMO

tsql: need help with returning latest record from a table

If I have data like following:
CustID, CustDate, CustCode
===========================
123 12/1/10 a
123 12/2/10 b
456 12/3/10 c
456 12/4/10 d
789 12/5/10 3
How would I write the query that would return the latest record for that customer within that table?
Result should be..
CustID, CustDate, CustCode
===========================
123 12/2/10 b
456 12/4/10 d
789 12/5/10 3
Please help me write query..
SELECT
CustId, CustDate, CustCode
FROM
MyTable
WHERE
NOT EXISTS
(
SELECT * FROM MyTable AS a_MyTable
WHERE a_MyTable.CustId = MyTable.CustId
AND a_MyTable.CustDate > MyTable.CustDate
)
Select CustId, CustDate, CustCode
From Table As T
Where CustDate = (
Select Max(T1.CustDate)
From Table As T1
Where T1.CustID = T.CustID
)