Select * query for sequences does not show all columns in output. (PG 11.5) - sequence

I am upgrading postgres from 9.1 to 11.5 .
but select query on sequences is returning different output in 11.5 as compared to 9.1, not all columns are shown in the output.
Output in 11.5
SELECT * FROM session_SEQ;
11.5:
last_value | log_cnt | is_called
------------+---------+-----------
1 | 0 | f
(1 row)
Output in 9.1:
SELECT * FROM session_SEQ;
sequence_name | last_value | start_value | increment_by | max_value | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+-------------+--------------+-----------+-----------+-------------+---------+-----------+-----------
session_seq | 1 | 1 | 1 | 99999999 | 1 | 1 | 0 | f | f
How can we display all the columns in 11.5? is there any workaround?*

You can query the pg_sequences and pg_class table to find this information out, like:
select relname,pg_sequence.* from pg_sequence inner join pg_class on pg_class.oid=pg_sequence.seqrelid;

Related

Oracle SQL Any comparision with subquery raises right paranthesis missing error

The query works fine with any operator for multiple values for any comparison.
SELECT Name, ID
from tblABC
where ID = ANY (1,2,3,4,5 )
But when a subquery is used for any comparison a right parenthesis missing error occurs
SELECT Name, ID
from tblABC
where ID = ANY (select ID from tblXYZ where ROWNUM <= 10 order by ID desc )
The subquery just gives the top 10 recent id entries from the selected table. Should there be a conversion to number or missing condition in this query?
The reason is order by, which is not necessary as it is evaluated after count stopkey (which is rownum < <constant>).
select *
from table(dbms_xplan.display_cursor(format => 'BASIC +PREDICATE'));
| PLAN_TABLE_OUTPUT |
| :----------------------------------------------------------------------- |
| EXPLAINED SQL STATEMENT: |
| ------------------------ |
| select /*+ gather_plan_statistics */ * from t where rownum < 5 order by |
| 1 asc |
| |
| Plan hash value: 846588679 |
| |
| ------------------------------------ |
| | Id | Operation | Name | |
| ------------------------------------ |
| | 0 | SELECT STATEMENT | | |
| | 1 | SORT ORDER BY | | |
| |* 2 | COUNT STOPKEY | | |
| | 3 | TABLE ACCESS FULL| T | |
| ------------------------------------ |
| |
| Predicate Information (identified by operation id): |
| --------------------------------------------------- |
| |
| 2 - filter(ROWNUM<5) |
| |
If you are on Oracle 12C+, then you may use fetch first:
select *
from dual
where 1 = any(select l from t order by 1 asc fetch first 4 rows only)
| DUMMY |
| :---- |
| X |
Or row_number() for older versions:
select *
from dual
where 1 = any (
select l
from (
select l, row_number() over(order by l asc) as rn
from t
)
where rn < 5
)
| DUMMY |
| :---- |
| X |
db<>fiddle here
It is order by part. It is not supported within sub-queries like this.
Just remove it. You don't need it for comparison anyway.
SELECT Name, ID
from tblABC
where ID = ANY (select ID from tblXYZ where ROWNUM <= 10 )
You can use FETCH FIRST <n> ROWS ONLY instead of using the old ROWNUM in the subquery.
For example:
SELECT Name, ID
from tblABC
where ID = ANY (select ID
from tblXYZ
order by ID desc
fetch first 10 rows only)
See running example at db<>fiddle.

How do I select rows with maximum value?

Given this table I want to retrieve for each different url the row with the maximum count. For this table the output should be: 'dell.html' 3, 'lenovo.html' 4, 'toshiba.html' 5
+----------------+-------+
| url | count |
+----------------+-------+
| 'dell.html' | 1 |
| 'dell.html' | 2 |
| 'dell.html' | 3 |
| 'lenovo.html' | 1 |
| 'lenovo.html' | 2 |
| 'lenovo.html' | 3 |
| 'lenovo.html' | 4 |
| 'toshiba.html' | 1 |
| 'toshiba.html' | 2 |
| 'toshiba.html' | 3 |
| 'toshiba.html' | 4 |
| 'toshiba.html' | 5 |
+----------------+-------+
What SQL query do I need to write to do this?
Try to use this query:
select url, max(count) as count
from table_name
group by url;
use aggregate function
select max(count) ,url from table_name group by url
From your comments it seems you need corelated subquery
select t1.* from table_name t1
where t1.count = (select max(count) from table_name t2 where t2.url=t1.url
)
If row_number support on yours sqllite version
then you can write query like below
select * from
(
select *,row_number() over(partition by url order by count desc) rn
from table_name
) a where a.rn=1

Comparing rows vs array elements postgres

I have a table A with n rows (200+) and different numeric columns.
I have a table B with m rows (100K+) and a column called multipliers, which is of type array (REAL[]). For every row in B, this array's length is n, ie. a multiplier for every numeric variable in A. The array is sorted to match the alphabetical order of the id field in A
Table A
id | values_1 | values_2
---|----------|-------------
1 | 11.2 | 10.2
2 | 21.9 | 12.5
3 | 30.0 | 26.0
4 | 98.0 | 11.8
Table B
id | multipliers
--------|-------------
dafcec | {2,3,4,9}
nkjhbn | {0,0,1,5}
ccseff | {1,2,0,5}
ddeecc | {0,0,0,1}
I need a query that returns the SUM( multipliers * values_1 ).
Like this:
b.id | sum(b.multipliers*a.value_1)
--------|----------------------------------
dafcec | 2*11.2 + 3*21.9 + 4*30.0 + 9*98.0
nkjhbn | 0*11.2 + 0*21.9 + 1*30.0 + 5*98.0
ccseff | 1*11.2 + 2*21.9 + 0*30.0 + 5*98.0
ddeecc | 0*11.2 + 0*21.9 + 0*30.0 + 1*98.0
I have tried with different subquerys, LATERAL joins and UNNEST, but I can't get a working result.
Any hints? Thanks!
the easiest, but I believe expensive way to sum array would be:
t=# with b as (select id,unnest(multipliers) u from b)
select distinct id, sum(u)over (partition by id) from b;
id | sum
----------+-----
ccseff | 8
nkjhbn | 6
ddeecc | 1
dafcec | 18
(4 rows)
and no fast alternative comes to my mind here...
further - If I get it right you want a cartesian product - all against all, then:
t=# with b as (select id,unnest(multipliers) u from b)
, ag as (select distinct id, sum(u)over (partition by id) from b)
select ag.sum * v1, a.id aid, ag.id idb
from ag
join a on true;
?column? | aid | idb
----------+-----+----------
89.6 | 1 | ccseff
175.2 | 2 | ccseff
240 | 3 | ccseff
784 | 4 | ccseff
67.2 | 1 | nkjhbn
131.4 | 2 | nkjhbn
180 | 3 | nkjhbn
588 | 4 | nkjhbn
11.2 | 1 | ddeecc
21.9 | 2 | ddeecc
30 | 3 | ddeecc
98 | 4 | ddeecc
201.6 | 1 | dafcec
394.2 | 2 | dafcec
540 | 3 | dafcec
1764 | 4 | dafcec
(16 rows)
Solved it.
It just needs to pack the values into an array and unpack them so they are comparable. It worked for me. The ORDER BY makes sure the packing occurs in the desired order.
SELECT id, SUM (field * multiplier) result FROM
(
with c as (
SELECT array_agg( values_1 ORDER BY name ASC) val1
from A
)
, ag as (
select
distinct id,
multipliers
from B
)
SELECT
ag.id,
unnest(c.val1) field,
unnest(ag.multipliers) multiplier
FROM
c, ag
) s
GROUP BY id

Efficient query to Group by column name in SQL or hive

Imagine I have a table with 2 columns m_1 and m_2:
m1 | m2
3 | 17
3 | 18
4 | 17
9 | 9
I would like to get a table with 3 columns:
m is the index of m (in my exemple 1 or 2)
d is the data contains in the table .
count is the number of occurence of each data, group by value and index.
In the example, the result is:
m | d | count
m_1 | 3 | 2
m_1 | 4 | 1
m_1 | 9 | 1
m_2 | 17| 2
m_2 | 18| 1
m_2 | 9 | 1
The first ligne mus be read as 'data 3 occurs 2 times in column m_1'?
A naive solution is to execute two times a parametric query like this:
for (i in 1 .. 2)
SELECT CONCAT('m_', i), m_i, count(*) FROM table GROUP BY m_i
But this algorithm scans my table two times. This is a problem since I have 255 columns m and bilion of rows.
Will the solution becomes easier if I use hive instead of a relational data base?
You can write this using union all and group by:
select colname, d, count(*)
from ((select 'm_1' as colname, m1 as d from t) union all
(select 'm_2' as colname, m2 as d from t)
) m12
group by colname, d;
posexplode(array(m1,m2))
select concat('m_',cast(pe.pos+1 as string)) as m
,pe.val as d
,count(*) as `count`
from mytable t
lateral view posexplode(array(m1,m2)) pe
group by pos
,val
;
+------+-----+--------+
| m | d | count |
+------+-----+--------+
| m_1 | 3 | 2 |
| m_1 | 4 | 1 |
| m_1 | 9 | 1 |
| m_2 | 9 | 1 |
| m_2 | 17 | 2 |
| m_2 | 18 | 1 |
+------+-----+--------+

Optimization by replacing subquery with named subquery having INLINE hint

Let's have these two tables:
create table table_x(
x_id varchar2(100) primary key
);
create table table_y(
x_id varchar2(100) references table_x(x_id),
stream varchar2(10),
val_a number,
val_b number
);
create index table_y_idx on table_y (x_id, stream);
Suppose we have millions of rows in each table and table_y contains from 0 to 10 rows per each x_id.
The queries in the following examples return 200 rows by filter substr(x_id, 2, 1) = 'B'.
It's required to optimize the query:
QUERY 1
select
x.x_id,
y.val_a,
y.val_b
from table_x x
left join (select
x_id,
max(val_a) KEEP (DENSE_RANK FIRST ORDER BY stream) as val_a,
max(val_b) KEEP (DENSE_RANK FIRST ORDER BY stream) as val_b
from table_y
group by x_id
) y on x.x_id = y.x_id
where substr(x.x_id, 2, 1) = 'B'; -- intentionally not use the primary key filter
------
PLAN 1
----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10000 | 2400000 | 22698 | 00:04:33 |
| * 1 | HASH JOIN OUTER | | 10000 | 2400000 | 22698 | 00:04:33 |
| * 2 | TABLE ACCESS FULL | TABLE_X | 10000 | 120000 | 669 | 00:00:09 |
| 3 | VIEW | | 10692 | 2437776 | 22029 | 00:04:25 |
| 4 | SORT GROUP BY | | 10692 | 245916 | 22029 | 00:04:25 |
| 5 | TABLE ACCESS FULL | TABLE_Y | 1069200 | 24591600 | 19359 | 00:03:53 |
----------------------------------------------------------------------------------
* 1 - access("X"."X_ID"="Y"."X_ID"(+))
* 2 - filter(SUBSTR("X"."X_ID", 2, 1)='B')
There's a way of significant optimization, so QUERY 2 returns rows 2-3 times faster than QUERY 1. The INLINE hint is сritically important, because without it the second performs as slow as the first one.
QUERY 2
with
table_y_total as (
select --+ INLINE
x_id,
max(val_a) KEEP (DENSE_RANK FIRST ORDER BY stream) as val_a,
max(val_b) KEEP (DENSE_RANK FIRST ORDER BY stream) as val_b
from table_y
group by x_id
)
select
x.x_id,
(select val_a from table_y_total y where y.x_id = x.x_id) as val_a,
(select val_b from table_y_total y where y.x_id = x.x_id) as val_b
from table_x x
where substr(x.x_id, 2, 1) = 'B';
------
PLAN 2
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10000 | 120000 | 669 | 00:00:09 |
| 1 | SORT GROUP BY NOSORT | | 1 | 19 | 103 | 00:00:02 |
| 2 | TABLE ACCESS BY INDEX ROWID | TABLE_Y | 100 | 1900 | 103 | 00:00:02 |
| * 3 | INDEX RANGE SCAN | TABLE_Y_IDX | 100 | | 3 | 00:00:01 |
| 4 | SORT GROUP BY NOSORT | | 1 | 20 | 103 | 00:00:02 |
| 5 | TABLE ACCESS BY INDEX ROWID | TABLE_Y | 100 | 2000 | 103 | 00:00:02 |
| * 6 | INDEX RANGE SCAN | TABLE_Y_IDX | 100 | | 3 | 00:00:01 |
| * 7 | TABLE ACCESS FULL | TABLE_X | 10000 | 120000 | 669 | 00:00:09 |
-----------------------------------------------------------------------------------------
* 3 - access("X_ID"=:B1)
* 6 - access("X_ID"=:B1)
* 7 - filter(SUBSTR("X"."X_ID", 2, 1)='B')
Since the first query uses less code duplication I would prefer to keep it.
Is there a hint or another trick to meet the following conditions both?
keep the first query code (QUERY 1)
force optimizer use the second plan (PLAN 2)
Perhaps you have oversimplified your code, but doesn't this do what you want:
select y.x_id,
max(y.val_a) KEEP (DENSE_RANK FIRST ORDER BY stream) as val_a,
max(y.val_b) KEEP (DENSE_RANK FIRST ORDER BY stream) as val_b
from table_y y
where substr(y.x_id, 2, 1) = 'B'
group by x_id;
I don't think the join to table x is unnecessary, as you have framed the question.
use index hint
select /*+index(index_name)*/ from table
Since full scan on table_x is the cheapest part of the plan, there's an approach with filtering it before joining table_y. Although optimizer decides to use full scan on table_y by default, hinting with index(y) helps to reduce timing to 110% of the QUERY 2's.
with
table_x_filtered as (
select x_id
from table_x
where substr(x_id, 2, 1) = 'B'
)
select /*+ index(y table_y_idx) */
x.x_id,
max(val_a) KEEP (DENSE_RANK FIRST ORDER BY stream) as val_a,
max(val_b) KEEP (DENSE_RANK FIRST ORDER BY stream) as val_b
from table_x_filtered x
left join table_y y on y.x_id = x.x_id
group by x.x_id;