I have four tables
TABLE_A
----------------
ID AName1 AName2
1 A11 A12
2 A21 A22
3 A31 A32
TABLE_B
------------
AID ID BName
1 B11 Ba11
1 B12 Ba12
1 B13 Ba13
1 B14 Ba14
2 B21 Ba21
2 B22 Ba22
3 B31 Ba31
TABLE_C
----------------
AID BID ID CName
1 B11 C11 Ca11
1 B11 C12 Ca12
1 B11 C13 Ca13
1 B12 C14 Ca14
1 B13 C15 Ca15
1 B13 C16 Ca16
1 B14 C17 Ca17
1 B14 C18 Ca18
1 B14 C19 Ca19
2 B21 C20 Ca20
2 B21 C21 Ca21
2 B22 C22 Ca22
2 B22 C23 Ca23
2 B22 C24 Ca24
2 B22 C25 Ca25
TABLE_D
----------------
AID BID ID DName
1 B11 D1 Da1
1 B11 D2 Da2
1 B11 D3 Da3
1 B12 D4 Da4
1 B12 D5 Da5
1 B13 D6 Da6
1 B13 D7 Da7
1 B13 D8 Da8
1 B13 D9 Da9
1 B14 D10 Da10
2 B21 D11 Da11
2 B21 D12 Da12
2 B21 D13 Da13
2 B22 D14 Da14
2 B22 D15 Da15
Given a single pair of AName1 and AName2, I would like to get unique values of BName and the corresponding arrays of CName and DName.
For example, given AName1 = A21 and AName2 = A22, I would like to get the following:
BName CName DName
B21 {Ca20, Ca21} {Da11, Da12, Da13}
B22 {Ca22, Ca23, Ca24, Ca25} {Da14, Da15}
I'm currently using the following query:
SELECT
b.BName,
array_agg(c.CName),
array_agg(d.DName)
FROM
TABLE_B
INNER JOIN
TABLE_A on b.AID=TABLE_A.ID
LEFT JOIN
TABLE_C c on c.BID = b.ID
LEFT JOIN
TABLE_D d on d.BID=b.ID
WHERE
TABLE_A.AName1 like 'A21' AND
TABLE_A.AName2 like 'A22'
GROUP BY
b.ID
This is repeating values as if it is also grouping on C and D:
BName CName DName
B21 {Ca20, Ca20, Ca20, Ca21, Ca21, Ca21} {Da11, Da12, Da13, Da11, Da12, Da13}
Does anyone know how I might be able to correct this issue? I'm using PostgreSQL version 9.2.
SQL Fiddle
select
b.bname,
array_agg(distinct c.cname),
array_agg(distinct d.dname)
from
table_b b
inner join
table_a a on b.aid = a.id
left join
table_c c on c.bid = b.id
left join
table_d d on d.bid = b.id
where
a.aname1 = 'A21' and
a.aname2 = 'A22'
group by b.bname
Related
I have a CSV file with ID, ID1, ID2, col1, col2, and col3 fields...I need to group the record based on the ID field and convert it to a UDT list.
ex:
ID ID1 ID2 COL1 COL2 COL3 COL4
1 AA 01 A B C D
1 AA 02 A B C D
1 AA 02 B C D E
1 AA 03 A B C D
2 BB 01 A B C D
2 BB 02 A B C D
3 CC 01 A B C D
3 CC 01 B C D E
THE OUTPUT SHOULD BE
1,[{ID1:"AA",ID2:"01"},{ID1:"AA",ID2:"02"},{ID1:"AA",ID2:"03"}]
2,[{ID1:"BB",ID2:"01"},{ID1:"BB",ID2:"02"}]
3,[{ID1:"CC",ID2:"01"}] (grouped by ID; rest of the ID fields in a list array)
I tried collect_list / collect_set to group the fields but could not convert them to an array.
Below is my table schema (I am using PostgreSQL 9.6.1)
my_table
------------
table_id SERIAL PRIMRY KEY,
A1 INTEGER,
A2 INTEGER,
A3 INTEGER,
A4 INTEGER,
A5 INTEGER,
A6 INTEGER,
A7 INTEGER,
A8 INTEGER,
A9 INTEGER,
A10 INTEGER,
A11 INTEGER,
A12 INTEGER,
A13 INTEGER,
A14 INTEGER,
A15 INTEGER,
A16 DOUBLE PRECISION,
A17 DOUBLE PRECISION
and i am trying to run below query in order to create a new table.
CREATE TABLE my_table_2 AS
SELECT
B1 AS C1
B3 AS C2,
B5 AS C3,
B7 AS C4 ,
B9 AS C5,
B11 AS C6 ,
B1 / CAST( NULLIF(B3, 0) AS FLOAT) AS C7,
B1 / CAST( NULLIF(B5, 0) AS FLOAT) AS C8,
B1 / CAST( NULLIF(B7, 0) AS FLOAT) AS C9,
B1 / CAST( NULLIF(B9, 0) AS FLOAT) AS C10,
B1 / CAST( NULLIF(B11, 0) AS FLOAT) AS C11,
B3 / CAST( NULLIF(B5, 0) AS FLOAT) AS C12,
B5 / CAST( NULLIF(B7, 0 )* NULLIF(B9,0) AS FLOAT) AS C13,
B2 AS C14 ,
B4 AS C15,
B6 AS C16,
B8 AS C17,
B10 AS C18,
B12 AS C19,
B2 / CAST(NULLIF(B4, 0) AS FLOAT) AS C20,
B2 / CAST(NULLIF(B6, 0) AS FLOAT) AS C21,
B2 / CAST(NULLIF(B8, 0) AS FLOAT) AS C22,
B2 / CAST(NULLIF(B10, 0) AS FLOAT) AS C23,
B2 / CAST(NULLIF(B12 , 0) AS FLOAT) AS C24
B4 / CAST(NULLIF(B6 , 0) AS FLOAT) AS C25
B6 / CAST(NULLIF(B8,0) * NULLIF( B10,0) AS FLOAT) AS C26
0.0 AS C27,
0.0 AS C28,
0.0 AS C29,
0.0 AS C30,
0.0 AS C31,
0.0 AS C32,
0.0 AS C33,
0.0 AS C34,
0.0 AS C35,
0.0 AS C36,
0.0 AS C37,
0.0 AS C38,
0.0 AS C39,
B13 AS C40
B14 AS C41,
B15 AS C42
FROM (
SELECT
table_id,
A1 - A2 + A3 AS B1,
A1 AS B2,
A4 - A5 AS B3,
A4 AS B4,
A6 - A7 AS B5,
A6 AS B6,
A8 - A9 AS B7,
A8 AS B8,
A10 - A11 AS B9,
A10 AS B10,
A12 - A13 AS B11,
A12 AS B12,
A14 AS B13,
A15 AS B14,
coalesce(coalesce(A16 * 100, 0) / NULLIF(A17, 0), 0) AS B15
FROM my_table
) v1;
I am running the above query as a background process using psql command
using below command
sudo -u postgres psql My_DB -X -a -f /tmp/test.sql > result.out 2>result.err &
Since my_table is a very huge table. But after sometime when I check result.err file. It has only one line saying
ERROR: integer out of range
For some sample ids in the WHere clause table gets generated without any issues but when i run it for entire table above error comes.
Can anyone explain why is this happening and how I can fix this?
Any of the + or - operations could cause this error, but the most likely cause is A16 * 100.
You can fix the problem by either avoiding operations that cause the overflow, or you could choose a data type like numeric or bigint that has a wider range of values.
check the multiplications
NULLIF(B7, 0 )* NULLIF(B9,0)
and
NULLIF(B8,0) * NULLIF( B10,0)
try to replace the order of calculation, the first division, then multiplication
( B5 / NULLIF(B7, 0) ) * NULLIF(B9,0) AS B15
( B6 / NULLIF(B8, 0) ) * NULLIF(B10,0) AS C26
My table contain below records.. Table Name : Cus1
Column: c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15
Records: 1 2 2 3 4 4 5 6 6 6 7 7 8 8 9 -1st record
1 2 3 3 3 4 4 5 5 5 5 6 7 7 8 -2nd record
How to get result like below using above table:
Column: c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15
Records: 1 2 3 4 5 6 7 8 9 NULL NULL NULL NULL NULL NULL -1st record
1 2 3 4 5 6 7 8 NULL NULL NULL NULL NULL NULL NULL -2nd record
its possible in DB2 using if condition ?
No idea what is meant by "using if condition", but perhaps the following may be of interest?
Setup:
create table cus1
( c1 dec(3), c2 dec(3), c3 dec(3), c4 dec(3), c5 dec(3)
, c6 dec(3), c7 dec(3), c8 dec(3), c9 dec(3), c10 dec(3)
, c11 dec(3), c12 dec(3), c13 dec(3), c14 dec(3), c15 dec(3)
)
;
insert into cus1 values
( 1, 2, 2, 3, 4, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9)
, ( 1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 5, 6, 7, 7, 8)
;
Use table data from setup to generate queries; each created here as a VIEW to be queried for the final result:
create view cus1_unpivot_view as
with
cus1_rn as
( select row_number() over() as rn
, a.*
from cus1 a
)
SELECT rn, cn, cn_val
FROM cus1_rn as C
, lateral
( values ( 1, C.c1 ), ( 6, C.c6 ), ( 11, C.c11 )
, ( 2, C.c2 ), ( 7, C.c7 ), ( 12, C.c12 )
, ( 3, C.c3 ), ( 8, C.c8 ), ( 13, C.c13 )
, ( 4, C.c4 ), ( 9, C.c9 ), ( 14, C.c14 )
, ( 5, C.c5 ), ( 10, C.c10 ), ( 15, C.c15 )
) AS X( cn, cn_val )
; /* create an unpivot view of columns to rows */
create view cus1_unmatched as
select a.rn, a.cn, b.cn_val
from cus1_unpivot_view as a
left join
( select distinct rn, cn_val
from cus1_unpivot_view as d
) as b
on a.rn=b.rn
and a.cn=b.cn_val
; /* Generate unmatched values to get NULL results */
create view cus1_pivot as
select rn
, max( case when cn=1 then cn_val end ) as c1
, max( case when cn=2 then cn_val end ) as c2
, max( case when cn=3 then cn_val end ) as c3
, max( case when cn=4 then cn_val end ) as c4
, max( case when cn=5 then cn_val end ) as c5
, max( case when cn=6 then cn_val end ) as c6
, max( case when cn=7 then cn_val end ) as c7
, max( case when cn=8 then cn_val end ) as c8
, max( case when cn=9 then cn_val end ) as c9
, max( case when cn=10 then cn_val end ) as c10
, max( case when cn=11 then cn_val end ) as c11
, max( case when cn=12 then cn_val end ) as c12
, max( case when cn=13 then cn_val end ) as c13
, max( case when cn=14 then cn_val end ) as c14
, max( case when cn=15 then cn_val end ) as c15
from cus1_unmatched
group by rn
; /* pivot row data back to columns with the NULLs */
Finally, query that last VIEW to omit the row-numbering and present the data; compare the results to the desired output:
select
c1 , c2 , c3 , c4 , c5
, c6 , c7 , c8 , c9 , c10
, c11 , c12 , c13 , c14 , c15
from cus1_pivot
order by rn
; -- the following is a likeness of a report from the above query:
....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+...
C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 C13 C14 C15
1 2 3 4 5 6 7 8 9 - - - - - -
1 2 3 4 5 6 7 8 - - - - - - -
******** End of data ********
I need to calculate the counts per city,state and country. For example if i have the following data in my table T1:
name city state country
------------------------------
name1 c1 s1 C1
name2 c1 s1 C1
name3 c2 s1 C1
name4 c3 s1 C1
name5 c4 s2 C1
name6 c5 s2 C1
name7 c5 s3 C1
name8 c12 s12 C2
the query should results in:
city state country citycount, statecount, countrycount
-------------------------------------------------------------------
c1 s1 C1 2 4 7
c2 s1 C1 1 4 7
c3 s1 C1 1 4 7
c4 s2 C1 1 2 7
c5 s2 C1 1 2 7
c5 s3 C1 1 1 7
c12 s12 C2 1 1 1
if i do group by and count then i need to write 3 different queries. But i want to do it in one query. please help.
You can use window functions, for example one solution could be this one:
SELECT DISTINCT city
,STATE
,country
,count(*) OVER (PARTITION BY city,STATE,country) AS citycount
,count(*) OVER (PARTITION BY STATE,country) AS statecount
,count(*) OVER (PARTITION BY country) AS countrycount
FROM T1
ORDER BY city
,STATE
,country
Please see a fiddle here.
I have a table:
servername description ObjectState
VM1 SP LA - W IN S V R S #P19 99 9999 999999 999 QTY 1 0
VM2 S PL A - V R STD #P29-9 9 99 QTY 2 : SPLVRENT #P3 999999 9 QTY 3 1
VM3 S PL A - WI NS V R S TD #P39-9 999 QTY 3 0
VM4 SPLA - WI NS V R STD #P59- 9 9 99 QTY 2 : S P LA - W IN SV RENT #P39-9999 QTY 3 : SPL A - WIN S VR SMB # P 3 9- 999 99 QTY 5 1
VM6 SPLA - W I NS VRSQ LSE R VE RS TD #P 6 9-9 9 9 9 QTY 6 0
VM5 SPLA - W IN S VRS TD #P59-9999 QTY 5 : SPLA - SQLSERVER-08 #P59-9999 QTY 5 0
VM7 SPLA - W I NSV R ST D #P79-9999 QTY 6 0
VM8 SPLA - W INS VR STD #P8 9-9 9 99 QTY 1 1
I wrote query like this
to split the description column like
SELECT
T.servername,
A.x.value('(/e/text())[1]', 'varchar(MAX)') [description],
A.x.value('(/e/text())[2]', 'varchar(25)') [ponumber],
A.x.value('(/e/text())[3]', 'varchar(2)') [qty],
A.x.value('(/e/text())[4]', 'char(1)') [ObjectState]
FROM
T1 AS T
CROSS APPLY
(SELECT T.[description] AS [text()] FOR XML PATH('')) AS R(s)
CROSS APPLY
(SELECT T.[ObjectState] as [text()] FOR XML PATH('')) AS B(t)
CROSS APPLY
(SELECT CAST('<e>' + REPLACE(R.s,':', '</e><e>') + '</e>' AS xml)) AS S(x)
CROSS APPLY
S.x.nodes('/e') AS N1(e)
CROSS APPLY
(SELECT CAST('<e>' + REPLACE(REPLACE(N1.e.value('text()[1]','varchar(MAX)'), '#', '</e><e>'), 'QTY', '</e><e>') + '</e>' AS xml)) AS A(x)
and I am getting output like this
servername description ponumber qty ObjectStat
VM1 SP LA - W IN S V R S P19 99 9999 999999 999 1 NULL
VM2 S PL A - V R STD P29-9 9 99 2 NULL
VM2 SPLVRENT P3 999999 9 3 NULL
I want the output in the colum Objectstate for
vm1 SP LA - W IN S V R S P19 99 9999 999999 999 1 0
vm2 S PL A - V R STD P29-9 9 99 2 1
vm2 SPLVRENT P3 999999 9 3 1
like this - How would I modify the above code to get the output I require?
In your query it looks like ObjectState is a field of its own. So...
SELECT
T.servername,
A.x.value('(/e/text())[1]', 'varchar(MAX)') [description],
A.x.value('(/e/text())[2]', 'varchar(25)') [ponumber],
A.x.value('(/e/text())[3]', 'varchar(2)') [qty],
T.ObjectState
FROM
#T AS T
CROSS APPLY
(SELECT T.[description] AS [text()] FOR XML PATH('')) AS R(s)
CROSS APPLY
(SELECT CAST('<e>' + REPLACE(R.s,':', '</e><e>') + '</e>' AS xml)) AS S(x)
CROSS APPLY
S.x.nodes('/e') AS N1(e)
CROSS APPLY
(SELECT CAST('<e>' + REPLACE(REPLACE(N1.e.value('text()[1]','varchar(MAX)'), '#', '</e><e>'), 'QTY', '</e><e>') + '</e>' AS xml)) AS A(x)