How can I extract multiple rows from a single one having 4 columns in PostgreSQL? - sql

I'm having a issue with a query in Postgres. I need to extract from a table with a specific pattern using a pure select. For example I have:
Column A
Column B
Column C
Column D
1
2
3
4
From this table I want to select something like this:
Column A
Column B
Column C
Column D
1
null
null
null
1
2
null
null
1
2
3
null
1
2
3
4
I don't really have a clue on how to do it efficiently. Anyone can help? Many thanks

You can cross join with a list of integers and use a conditional expression:
with n as (select * from(values(1),(2),(3),(4))x(n))
select
case when n >= cola then cola end cola,
case when n >= colb then colb end colb,
case when n >= colc then colc end colc,
case when n >= cold then cold end cold
from n
cross join t;
working Fiddle

Related

How to pull UNIQUE value and add DISTINCT COUNT multiple criteria in BIGQUERY

this is the table i have
ColA
ColB
ColC
A
327452
0
B
327478
8
A
1507089
1
A
1507089
4
C
1625746
9
C
1529
2
B
1625759
7
B
1625760
5
A
20366530
3
C
1529
0
So I want to make a new table with 2 column where it contain unique value of ColA in first column and in the second column is count distinct of ColB where ColC > 0, which it's suppose look like this:
ColK
ColL
A
2
B
3
C
2
in Spreadsheet I can just simply use a formula like this:
1st Column (Col K):
=UNIQUE(A:A)
2nd Column (Col L):
COUNTA(UNIQUE(FILTER($C$2:$C,($B$2:$B=$K3) * ($D$2:$D>0))))
But now I try to learn BIGQUERY and try to write a code like this but it didn't work:
SELECT
DISTINCT ColA
COUNT(DISTINCT ColB IF((ColA=[#[ColA]])*(ColC>0)))
FROM
`mi-trial-365509.Trial.MI 17012022`
LIMIT
1000
Can someone please help me here?, I'm really new in BIGQUERY

To find total number of rows

I have a table like this
Table1
=======
A B
8 5
2 9
null 4
2 5
How to find total number of rows from table1,note if any column value is null in a row then that row should be considered as 2 rows?
I have tried with count(*)*2 and nvl function it doesn't work
Try this
SELECT SUM(CASE WHEN A IS NULL OR B IS NULL THEN 2 ELSE 1 END) AS CountVal
FROM TABLE1
Fiddle Demo
O/P:
COUNTVAL
--------
5
COUNT() is rowbased.. you can tweak it using SUM() instead..
select sum(NVL2(a,NVL2(b,1,2),2)) FROM TABLE1
CASE as suggested by #Vignesh is the simplest and more readable !!
COUNT() can also done like this.. But NOT a optimal solution at all!
SELECT COUNT(1) FROM
(
SELECT NVL(a,NVL(b,1)) FROM TABLEA
UNION ALL
SELECT NVL(a,NVL(b,1)) FROM TABLEA
WHERE A OR B iS NULL
)

row numbering based on the number of rows returned by query

I have requirement, where i have to give rownumber for each record returned by my query based on the total count of the rows returned.
lets say a rownumber for each 3 record.
for ex.
colA colB colC(rowno)
1 abc 1
2 asd 1
3 asw 1
4 tre 2
5 cfr 2
6 dfr 2
7 sdf 3
I tried with row_number() over (partition by count(*) order by colA) but it gives the row number as 1 for all the records.
Any idea would help.
Use some maths and the integer division rules:
select colA,colB,(ROW_NUMBER() OVER (ORDER BY colA)+2)/3 as colC
from table
The two integer constants are related - you always want the inner constant (2) to be one less than the number of rows which should be assigned the same number (3).
try this
SELECT ROW_NUMBER() OVER (Order by [Col]) as ColID FROM [TABLE NAME]
WHERE colC = 3

how to combine Y or N or null values

still not found the solution described in update 2
thx for help
ill try to explain my issue with my poor english. hope someone can solve my problem.
i got the following table
A B
1 Y
2 null
3 Y
what result i want?
in dependency of the rank in column A i want to combine column B.
the result in that example is ... no result
the reason is because there is a null in rank 2 and the next and the last rank (=3) has a value (=Y).
next example
A B
1 Y
2 null
3 null
result i want is
A B
1 Y
because the way after is free... means 2 and the last 3 has null
another example
A B
1 null
2 N
3 null
again no result is what i want in this case. because first =1 has null value.
i try now to conclude ... if n(e.g. 2) of column B has value Y or N then the elements bevor (in this 1) must have the value Y or N.
thank you very much. i tried different technics without any success...
UPDATE 1
thank you fast comment
some example dates with expected result
example 1
A B
1 Y
2 N
3 null
4 null
expected result
A B
2 N
example 2
A B
1 N
2 Y
3 N
4 null
expected result
A B
3 N
example 3
A B
1 null
2 Y
3 Y
4 null
expected result
no result
example 4
A B
1 Y
2 Y
3 null
4 Y
expected result
no result
UPDATE 2
forget the basic case
A B
1 Y
2 N
3 Y
expected result
A B
3 N
Establish the highest value of A where B is Y or N, and the lowest value of A where B is null. Provided the first value is lower than the second value you have a valid result set.
select yt.A
, yt.B
from
( select max(case when B is not null then A else null end) as max_b_yn
, min(case when B is null then A else null end) as min_b_null
from your_table ) t1
, your_table yt
where ( t1.min_b_null is null
or t1.max_b_yn < t1.min_b_null )
and yt.A = t1.max_b_yn
/
I think you want the last row before the first NULL. If this is correct, then the following gets what you want:
select t.*
from t join
(select min(A) as NullA from t where B is NULL) t2
on t.A = t2.NullA - 1
Ah, I see. To get the last row with an "N":
select t.*
from t
where t.A in (select max(A) as MaxA
from t join
(select min(A) as NullA from t where B is NULL) t2
on t.A < t2.NullA
where t.B = 'N'
)
OK, I think I have what you need. It grabs the last row that has a value in column B as long as there isn't a row with a NULL that precedes it.
select MAX(A), B
from table_a
where B IS NOT NULL
and table_a.A > (
select MIN(A)
FROM table_a
WHERE B IS NULL
)
Group by B
select top 1 A, B
from #Temp
where B is not null
order by A desc
or
select top 1 A, B
from #Temp
where B = 'N'
order by A desc

Merge unique rows based on single column

I was just trying to do some herculean task with Oracle.
I have a table containing 3 columns
ColA ColB ColC ColD
---------------------------
123 N null 1
100 Y AAAA 1
123 Y XXXX 2
100 Y YYYY 2
I need to update ColB and ColC to show following result set.
ColA ColB ColC ColD
-------------------------------
123 Y XXXX 1
100 Y AAAA\YYYY 1
123 Y XXXX 2
100 Y YYYY 2
I need to update ColB with Y if any of the unique records contain Y else N.
And for ColC I want to update the values separated by a \ where both rows contains a value else just the value.
I have tried to do this with update query but ghosh......... It seems impossible.
Can any one suggest a possible solution or something?
I have been told to use PL/SQL if required. Will that do?
PS: I have also seen the other questions that seems similar but havn't got any solution yet.
EDIT: We need to update just those rows where ColD is 1.
A query to find how colB and colC will look:
select
colA,
case when count(case when colB='Y' then 1 end) > 0
then 'Y'
else 'N'
end as colB,
LISTAGG(colC, '\') WITHIN GROUP (ORDER BY colA) AS colC
from your_table
group by colA;
From this, you just shoot a MERGE like
update your_table a
using query b
on (a.colA=b.colB and colD=2)
when matched then update
a.colB=b.colB,
a.colC=b.colC