Combine rows in a table using the a column as reference [PSQL] - psql

I have a postgresql table like this:
| id | date | status |
|------|------------|--------|
| id1 | 2019-01-01 | ON |
| id1 | 2019-01-02 | OFF |
| id1 | 2019-01-03 | ON |
How can I combine the rows into sth like this:
| id | on_date | off_date |
|------|------------|------------|
| id1 | 2019-01-01 | 2019-01-02 |
| id1 | 2019-01-03 | |
OFF status always inserted after ON status (there will be a on_date before off_date)
My current solution is:
WITH ons AS (
SELECT id, row_number() OVER(ORDER BY date) as row_num, date as on_date
FROM table
WHERE status = 'ON' AND id = id1),
offs AS (
SELECT id, row_number() OVER(ORDER BY date) as row_num, date as off_date
FROM table
WHERE status = 'OFF' AND id = id1)
SELECT ons.id, ons.on_date, offs.off_date
FROM ons
LEFT JOIN offs ON ons.id = off.id AND ons.row_num = offs.row_num
Can I do this with simpler query? Thanks.

use below SQL :
select tt.id, tt.date as on_date, (select idate from
table where id=tt.id and status='OFF' and
date>=tt.idate and rownum<2) as off_date from table tt
where status='ON'

I think you get the result using below query:
SELECT id,on_date,off_date from (SELECT id,date as on_date,'' as off_date FROM test WHERE status = 'ON' UNION ALL SELECT id,'' as on_date,date as off_date FROM test WHERE status = 'OFF') as a

Related

Not null query extremely slow in ajax request partial

I have this simple scope
scope :has_video_link,
-> { where.not(video_link: nil) }
I use it like so in my controller
#videos = Message .featured
.includes(:user, :company, :forum, :topic)
.published
.unremoved
.approved
.has_video_link
.order(created_at: :desc)
.paginate(
page: page,
per_page: limit)
Which I call like so
before_action only: :index
skip_before_action :verify_authenticity_token
def index
self.page_title = 'Home'
fetch_videos
end
That works just fine, and my page loads in under a second on prod no problem. My issue is I have an ajax request that calls this
def videos
fetch_videos
respond_to do |format|
format.js
end
end
On dev this works great but in prod this takes over 60 seconds....
First image is from the first times its called (4ms)
2nd image is the ajax call 69000ms...
Any ideas? How do i fix this?? Thank you!!
edit: here is the explain
EXPLAIN for: SELECT `messages`.* FROM `messages` WHERE `messages`.`is_featured` = 1 AND (messages.created_at<='2021-06-04 12:36:22.241601') AND `messages`.`is_removed` = 0 AND `messages`.`is_approved` = 1 AND (`messages`.`video_link` IS NOT NULL) ORDER BY `messages`.`created_at` DESC LIMIT 5 OFFSET 0
+----+-------------+----------+------------+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+---------+------+------+----------+------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+---------+------+------+----------+------------------------------------+
| 1 | SIMPLE | messages | NULL | range | index_messages_on_is_removed_and_user_id_and_created_at,index_messages_on_is_removed_and_message_type_and_created_at,index_messages_on_is_removed_company_id_type_created_at,index_messages_on_is_removed_company_id_created_at_id_user_id,index_messages_on_is_removed_and_created_at,index_messages_on_is_removed_company_id_created_at_rating_count,index_messages_on_is_removed_company_id_user_role_created_at,index_messages_on_is_removed_and_company_id_and_rating_total,index_messages_on_is_removed_and_forum_id_and_created_at,index_messages_on_is_approved,index_messages_on_is_removed_and_is_approved | index_messages_on_is_removed_and_created_at | 7 | NULL | 3470 | 9.0 | Using index condition; Using where |
+----+-------------+----------+------------+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------+---------+------+------+----------+------------------------------------+
1 row in set (0.00 sec)
EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 594568
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | users | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.0 | NULL |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set (0.00 sec)
EXPLAIN for: SELECT `companies`.* FROM `companies` WHERE `companies`.`id` IN (564013, 562440)
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | SIMPLE | companies | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 2 | 100.0 | Using where |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set (0.01 sec)
EXPLAIN for: SELECT `forums`.* FROM `forums` WHERE `forums`.`id` IN (12224, 7759)
+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | SIMPLE | forums | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 2 | 100.0 | Using where |
+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set (0.00 sec)
EXPLAIN for: SELECT `topics`.* FROM `topics` WHERE `topics`.`id` IN (684474, 684473, 684472, 684470, 684467)
+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | SIMPLE | topics | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 5 | 100.0 | Using where |
+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set (0.00 sec)
Solved this issue. All I had to do was simply index video_links and that fixed my issue right up!

Simple join in Aqueduct

I'm newbie in a backend development and stuck with a simple request and ask for help.
I am trying to get a simple join:
select * from product a, product_barcode b
where a.productid = b.productid
Structure of the classes:
Product
class Product extends ManagedObject<product> implements product {}
class product {
#primaryKey
int productid;
String rusname;
String engname;
ManagedSet<Product_barcode> products;
}
Product_barcode
Class Product_barcode extends ManagedObject<product_barcode>
implements product_barcode {}
class product_barcode {
#primaryKey
int productid;
String barcode;
#Relate(#products)
Product product;
}
Request
#Operation.get()
Future<Response> getProducts() async {
final productQuery = Query<Product>(context)..join(set: (a) => a.products);
final res = await productQuery.fetch();
return Response.ok(res);
}
When i make a request I am getting error:
SELECT t0.productid,t0.rusname,t0.engname,t1.productid,t1.barcode,t1.product_productid FROM product t0 LEFT OUTER JOIN product_barcode t1 ON t0.productid=t1.product_productid
column t1.product_productid does not exist
What I am doing wrong? I do not have a column product_productid in my database
Update
Table structure
drugs=# \dt product_barcode
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+----------
public | product_barcode | table | druguser
(1 row)
drugs=# \d product_barcode
Table "public.product_barcode"
Column | Type | Collation | Nullable | Default
-----------+-------------------+-----------+----------+---------
productid | integer | | not null |
barcode | character varying | | not null |
Indexes:
"product_barcode_pk" PRIMARY KEY, btree (productid, barcode)
drugs=# \dt product
List of relations
Schema | Name | Type | Owner
--------+---------+-------+----------
public | product | table | druguser
(1 row)
drugs=# \d product
Table "public.product"
Column | Type | Collation | Nullable | Default
-------------------------+--------+-----------+----------+---------
productid | bigint | | not null |
rusname | text | | |
engname | text | | |
registrationdate | text | | |
dateofcloseregistration | text | | |
registrationnumber | text | | |
composition | text | | |
zipinfo | text | | |
producttypecode | text | | |
marketstatusid | text | | |
Indexes:
"product_pkey" PRIMARY KEY, btree (productid)

googlesheet - Call month API in query statement not work as expected

To summarize each month's balance, I try to call month API in query statement. but sounds like the month API always return (month - 1) but not month.
Example data:
| Type | TransDate | Amount |
|---------+------------+---------|
| Sale | 08/13/2017 | -40.97 |
| Return | 08/10/2017 | 127.48 |
| Payment | 08/07/2017 | 2194.45 |
| Sale | 08/07/2017 | -100.97 |
| Sale | 08/06/2017 | -143.44 |
| Sale | 07/02/2017 | -143.44 |
| Sale | 07/03/2017 | -7.55 |
| Sale | 08/04/2017 | -8.03 |
I use below formula:
=query(A:C,"select MONTH(B),sum(C) where A = 'Sale' or A = 'Return' group by MONTH(B) label MONTH(B) 'Month',sum(C) 'Total'")
The result table:
| Month | Total |
|-------+---------|
| 6 | -150.99 |
| 7 | -165.93 |
The month should be 7 and 8, but actually it return 6 and 7.
As the documentation says:
Returns the zero-based month value from a date or datetime value. For example: month(date "2009-02-05") returns 1. Note: the months are 0-based, so the function returns 0 for January, 1 for February, etc.
As #puts said, the index is start from 0, fix that with a offset:
=query(A:E,"select MONTH(B)+1,sum(E) where A = 'Sale' or A = 'Return' group by MONTH(B) label MONTH(B)+1 'Month',sum(E) 'Total'")

Query optimization - avoid full outer join

below is the data scripts used.
create table enab_test (ban varchar2(10),DVR_IND char(1));
create table oms_test (ban varchar2(10),DVR_IND char(1));
insert into enab_test values('111111111','Y');
insert into enab_test values('123456789','N');
insert into enab_test values('321654987','N');
insert into enab_test values('444444444','Y');
insert into enab_test values('111111111','Y');
insert into enab_test values('741258963','Y');
insert into oms_test values('111111111','Y');
insert into oms_test values('222222222','N');
insert into oms_test values('333333333','N');
insert into oms_test values('444444444','N');
insert into oms_test values('555555555','Y');
insert into oms_test values('666666666','N');
Here i'm trying to get the count of bans present in enab_test table where if the ban having dvr_ind = 'Y' then it is counted as one and if there are many with same ban then it is summed up. if there are same ban in Oms with dvr_ind = 'Y'. the count is subracted like enab_test - oms_test for bans. if we have any negative count while subracting from enab_test - oms_test then the count is made zero. and viceversa(oms_test-enab_test).
below is the query I worked on.
select nvl(enab.ENAB_COUNT,0) as ENAB_COUNT,
case when nvl(enab.ENAB_COUNT,0) - nvl(oms.OMS_COUNT,0) > 0
then nvl(enab.ENAB_COUNT,0) - nvl(oms.OMS_COUNT,0)
else 0
end as IN_ENAB_NOT_OMS
from (
select ban, count(*) as OMS_COUNT from oms_test
where dvr_ind = 'Y'
group by ban order by ban
) oms
full outer join (
select ban, count(*) as ENAB_COUNT from enab_test
where dvr_ind = 'Y'
group by ban order by ban
) enab
on oms.BAN = enab.BAN
Below is the output of the query
ENAB_COUNT IN_ENAB_NOT_OMS
2 1
0 0
1 1
1 1
Run Plan For the above query with original data is
Plan hash value: 2599843784
---------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6705K| 166M| | 10M (9)| 33:33:17 |
| 1 | VIEW | VW_FOJ_0 | 6705K| 166M| | 10M (9)| 33:33:17 |
|* 2 | HASH JOIN FULL OUTER| | 6705K| 255M| 204M| 10M (9)| 33:33:17 |
| 3 | VIEW | | 6703K| 127M| | 4767K (9)| 15:53:31 |
| 4 | SORT GROUP BY | | 6703K| 76M| 14G| 4767K (9)| 15:53:31 |
|* 5 | TABLE ACCESS FULL| OMS_TEST | 764M| 8749M| | 3335K (7)| 11:07:08 |
| 6 | VIEW | | 6705K| 127M| | 5278K (9)| 17:35:37 |
| 7 | SORT GROUP BY | | 6705K| 76M| 15G| 5278K (9)| 17:35:37 |
|* 8 | TABLE ACCESS FULL| ENAB_TEST | 805M| 9215M| | 3770K (7)| 12:34:05 |
---------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OMS"."BAN"="ENAB"."BAN")
5 - filter("DVR_IND"='Y')
8 - filter("DVR_IND"='Y')
I have created the above query and works fine on smaller data. its taking too much time if i'm having lot of records.Is there any way to remove full outer join and optimize the query or any other ways to optimize ?

Grouping in MDX Query

I am very newbie to MDX world..
I want to group the Columns based on only 3 rows. But, need join for 4th row also..
My query is :
SELECT
( {
[Measures].[Live Item Count]
}
) DIMENSION PROPERTIES parent_unique_name ON COLUMNS,
Crossjoin(
crossjoin(
[Item].[Class].&[Light],
[Item].[Style].&[Fav]
[Item].[Season Year].members),
[Item].[Count].children ) on rows
FROM Cube
Output comes as :
Light(Row) | FAV(Row) | ALL(Row) | 16(Row) | 2(col)
Light(Row) | FAV(Row) | ALL(Row) | 7(Row) | 1(col)
Light(Row) | FAV(Row) | 2012(Row) | 16(Row)| 2(col)
Light(Row) | FAV(Row) | 2011(Row) | 7(Row) | 1(col)
But, I want my output to be displayed as:
Light(Row) | FAV(Row) | ALL(Row) | | 3(col)
Light(Row) | FAV(Row) | 2012(Row) | 16(Row)| 2(col)
Light(Row) | FAV(Row) | 2011(Row) | 7(Row) | 1(col)
i.e., I want to group my first two rows such that there is no duplicate 'ALL' in 3rd column..
Thanks in advance
Try this - using the level name Season Year with the Attribute name Season Year will pick up every member without teh ALL member:
SELECT
( {
[Measures].[Live Item Count]
}
) DIMENSION PROPERTIES parent_unique_name ON COLUMNS,
Crossjoin(
crossjoin(
[Item].[Class].&[Light],
[Item].[Style].&[Fav]
[Item].[Season Year].[Season Year].members),
[Item].[Count].children ) on rows
FROM Cube
You can use this query if there is an All member on the [Item].[Count] hierarchy:
SELECT {[Measures].[Live Item Count]} DIMENSION PROPERTIES parent_unique_name ON COLUMNS,
Crossjoin(
Crossjoin([Item].[Class].&[Light], [Item].[Style].&[Fav]),
Union(
Crossjoin({"All member of [Item].[Season Year]"}, {"All member of [Item].[Count]"}),
Crossjoin(Except([Item].[Season Year].members, {"All member of [Item].[Season Year]"}), [Item].[Count].children),
) ON ROWS
FROM Cube

Resources