How for this table x:
pk - uid | post_id | date - timestamp | likes
1 1 01.01.2020 1
2 1 01.01.2021 5
3 2 01.01.2020 1
4 4 01.01.2021 3
5 4 01.01.2022 5
6 4 01.01.2023 10
Using two dates (range):
const [start_date, end_date] = ['01.01.2021', '01.01.2022']
Get rows in time range (one for each post_id), closest to start_date
pk - uid | post_id | date - timestamp | likes
2 1 01.01.2021 5
4 4 01.01.2021 3
and end_date (separate query):
pk - uid | post_id | date - timestamp | likes
2 1 01.01.2021 5
3 2 01.01.2020 1
5 4 01.01.2022 5
I was traying to do it like this, but got duplicate post_id's:
SELECT uid, post_id, like
FROM x
WHERE date <= ${end_date}
GROUP BY uid, post_uid
ORDER BY date DESC
Bonus question - i can do this using js, with 2 result arrays above, but maybe i can get result that will be difference of end_date rows likes - start date rows:
pk - uid | post_id | likes
2 1 0
4 4 2
You can use window functions first_value() and last_value() to accomplish this:
select distinct first_value(uid) over w as uid, post_id,
first_value(likes) over w as oldest_likes,
last_value(likes) over w as newest_likes,
last_value(likes) over w - first_value(likes) over w as likes
from x
where ddate between '2021-01-01' and '2022-01-01'
window w as (partition by post_id
order by ddate
rows between unbounded preceding and unbounded following)
;
uid | post_id | oldest_likes | newest_likes | likes
-----+---------+--------------+--------------+-------
2 | 1 | 5 | 5 | 0
4 | 4 | 3 | 5 | 2
(2 rows)
Related
I have a table below:
id
product_id
priceĀ
1
1
100
2
1
150
3
2
120
4
2
190
5
3
100
6
3
80
I want to select cheapest price for product and sort them by price
Expected output:
id
product_id
price
6
3
80
1
1
100
3
2
120
What I try so far:
`
repository.createQueryBuilder('products')
.orderBy('products.id')
.distinctOn(['products.id'])
.addOrderBy('price')
`
This query returns, cheapest products but not sort them. So, addOrderBy doesn't effect to products. Is there a way to sort products after distinctOn ?
SELECT id,
product_id,
price
FROM (SELECT id,
product_id,
price,
Dense_rank()
OVER (
partition BY product_id
ORDER BY price ASC) dr
FROM product) inline_view
WHERE dr = 1
ORDER BY price ASC;
Setup:
postgres=# create table product(id int, product_id int, price int);
CREATE TABLE
postgres=# insert into product values (1,1,100),(2,1,150),(3,2,120),(4,2,190),(5,3,100),(6,3,80);
INSERT 0 6
Output
id | product_id | price
----+------------+-------
6 | 3 | 80
1 | 1 | 100
3 | 2 | 120
(3 rows)
I have little problem with counting cells with particular value in one row in MSSMS.
Table looks like
ID
Month
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
11
12
13
14
15
16
...
31
5000
1
null
null
1
1
null
1
1
null
null
2
2
2
2
2
null
null
3
3
3
3
3
null
...
1
I need to count how many cells in one row have value for example 1. In this case it would be 5.
Data represents worker shifts in a month. Be aware that there is a column named month (FK with values 1-12), i don't want to count that in a result.
Column ID is ALWAYS 4 digit number.
Possibility is to use count(case when) but in examples there are only two or three columns not 31. Statement will be very long. Is there any other option to count it?
Thanks for any advices.
I'm going to strongly suggest that you abandon your current table design, and instead store one day per month, per record, not column. That is, use this design:
ID | Date | Value
5000 | 2021-01-01 | NULL
5000 | 2021-01-02 | NULL
5000 | 2021-01-03 | 1
5000 | 2021-01-04 | 1
5000 | 2021-01-05 | NULL
...
5000 | 2021-01-31 | 5
Then use this query:
SELECT
ID,
CONVERT(varchar(7), Date, 120),
COUNT(CASE WHEN Value = 1 THEN 1 END) AS one_cnt
FROM yourTable
GROUP BY
ID,
CONVERT(varchar(7), Date, 120);
To get 2 rows from each group I can use ROW_NUMBER() with condition <= 2 at last but my question is what If I want to get different limits on each group e.g 3 rows for section_id 1, 1 rows for 2 and 1 rows for 3?
Given the following table:
db=# SELECT * FROM xxx;
id | section_id | name
----+------------+------
1 | 1 | A
2 | 1 | B
3 | 1 | C
4 | 1 | D
5 | 2 | E
6 | 2 | F
7 | 3 | G
8 | 2 | H
(8 rows)
I get the first 2 rows (ordered by name) for each section_id, i.e. a result similar to:
id | section_id | name
----+------------+------
1 | 1 | A
2 | 1 | B
5 | 2 | E
6 | 2 | F
7 | 3 | G
(5 rows)
Current Query:
SELECT
*
FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY section_id ORDER BY name) AS r,
t.*
FROM
xxx t) x
WHERE
x.r <= 2;
Create a table to contain the section limits, then join. The big advantage being that as new sections are required or limits change maintenance is reduced to a single table update and comes at very little cost. See example.
select s.section_id, s.name
from (select section_id, name
, row_number() over (partition by section_id order by name) rn
from sections
) s
left join section_limits sl on (sl.section_id = s.section_id)
where
s.rn <= coalesce(sl.limit_to,2);
Just fix up your where clause:
with numbered as (
select row_number() over (partition by section_id
order by name) as r,
t.*
from xxx t
)
select *
from numbered
where (section_id = 1 and r <= 3)
or (section_id = 2 and r <= 1)
or (section_id = 3 and r <= 1);
I have a table for customers like this
cust_id | date_signed_up | location_id
-----------------------------------------
1 | 2019/01/01 | 1
2 | 2019/03/05 | 1
3 | 2019/06/17 | 1
What I need is to have a monthly count but having the months even if its 0. Ex:
monthly_count | count
-------------------------
Jan | 1
Feb | 0
Mar | 1
Apr | 0
(months can be in numbers)
Right now I made this query:
SELECT date_trunc('MONTH', (date_signed_up::date)) AS monthly, count(customer_id) AS count FROM customer
WHERE group_id = 1
GROUP BY monthly
ORDER BY monthly asc
but it's giving me just for the months there's information, skipping the ones where it's zero. How can I get all the months even if they have or not information.
You need a list of months.
How to generate Month list in PostgreSQL?
SELECT a.month , count( y.cust_id )
FROM allMonths a
LEFT JOIN yourTable y
ON a.month = date_trunc('MONTH', (date_signed_up::date))
GROUP BY a.month
I have table column like;
Documents
------------
1 2 3
1 2
2 3
1
4 5 1 3
Data under document column indicates the type of document; for e.g
1 indicates passport
2 indicates School id and so on.....
I want the column data as separate data with percentage calculation. like;
Basically i want to show percentage for each data...
Documents percentage
-------------------------
1 10%
2 2%
3 1%
4 25%
5 30%
I want to show data as separate data with their percentage.
can we build query in postgres to achive this????
You should convert the strings to arrays and unnest them, then you can calculate total and percentages:
create table test (documents text);
insert into test values
('1 2 3'),
('1 2'),
('2 3'),
('1'),
('4 5 1 3');
with docs as (
select doc
from test, unnest(string_to_array(documents, ' ')) doc
),
total as (
select count(*) as total
from docs
)
select doc, count(doc), count(doc)* 100/ total as percentage
from docs, total
group by doc, total
order by 1;
doc | count | percentage
-----+-------+------------
1 | 4 | 33
2 | 3 | 25
3 | 3 | 25
4 | 1 | 8
5 | 1 | 8
(5 rows)
with t(s) as ( values
('1 2 3'),('1 2'),('2 3'),('1'),('4 5 1 3')
)
select distinct s,
count(*) over(partition by s) * 100.0 /
count(*) over() as percentage
from (
select regexp_split_to_table(s, ' ') as s
from t
) t
;
s | percentage
---+---------------------
5 | 8.3333333333333333
4 | 8.3333333333333333
3 | 25.0000000000000000
1 | 33.3333333333333333
2 | 25.0000000000000000