Sybase get last record of record group - sql

I have a table like this
id ref status date
1 150 P 10/01/2010
2 150 P 11/01/2010
3 150 P 12/01/2010
4 151 P 10/01/2010
5 151 C NULL
6 152 P 11/01/2010
7 152 P 12/01/2010
8 152 C NULL
And what i want is to retrieve all the records that either have a status equals to C and (for those who have the status P) the last record according to the column date.
For example:
id ref status date
3 150 P 12/01/2010
5 151 C NULL
8 152 C NULL
So far I have tried to do subquerys but i dont get to have the last record according to date.
I´m using Sybase 8.0.2.4542. Thank you so much guys!!

Try to use the solution:
select id, ref, status, max(date)
from table
where status = 'P'
group by id, ref, status, date
union all
select id, ref, status, date
from table
where status = 'C'
with one query:
select *from
(select id, ref, status, max(date)
from table
where status = 'P'
group by id, ref, status, date
union all
select id, ref, status, date
from table
where status = 'C') RES

Related

group by and aggregate from tall to wide data in bigquery sql

Hi I want to aggregate group by and change it from tall to wide data in bigquery, how do I do so? I have a lot of sources and here's a sample data.
Here's the table
date
source
price
id
2022-01-01
A
2
1
2022-01-02
A
2
1
2022-01-03
A
4
1
2022-01-04
A
4
1
2022-01-01
B
1
1
2022-01-02
B
1
1
2022-01-03
B
3
1
2022-01-04
B
3
1
2022-01-01
A
2
2
2022-01-02
A
2
2
2022-01-03
A
4
2
2022-01-04
A
4
2
2022-01-01
B
1
2
2022-01-02
B
1
2
2022-01-03
B
3
2
2022-01-04
B
3
2
into
fields of min from price from all source for group by id and min price per source group by id
id
minPrice
minPriceSourceA
minPriceSourceB
1
2.5
3
2
2
2.5
3
2
Here's my current code
with Amin as
(
select
id,source,
min(price) min price
from table
where source ="A"
group by 1,2
),
Bmin as
(
select
id,source,
min(price) min price
from table
where source ="B"
group by 1,2
),
select
t1.id,t1.minprice,
Amin.minprice minPriceSourceA,
Bmin.minprice minPriceSourceB
from(
select
id,source,
min(price) minprice
from table
group by 1,2) t1
left join Amin on t1.id=Amin.id
left join Bmin on t1.id=Bmin.id
The problem is I have over 100 sources and id, if I do query manually the code will be very long. Is there an efficient way to do this?
You can use PIVOT to transpose rows into columns and get the MIN of a list of columns at once:
with sample as (
select "2022-01-01" as date, "A" as source, 2 as price, "1" as id
UNION ALL
select "2022-01-02" as date, "A" as source, 1 as price, "1" as id
UNION ALL
select "2022-01-04" as date, "B" as source, 1 as price, "1" as id
UNION ALL
select "2022-01-04" as date, "A" as source, 2 as price, "2" as id
UNION ALL
select "2022-01-04" as date, "A" as source, 4 as price, "2" as id
UNION ALL
select "2022-01-04" as date, "B" as source, 3 as price, "2" as id
),
min_by_source as (
SELECT * FROM
(SELECT id, source, price FROM sample)
PIVOT(MIN(price) AS minPrice FOR source IN ('A', 'B')) -- add here the others sources
),
min_global as (
SELECT id, MIN(price) AS minPrice
FROM sample
GROUP BY id
)
SELECT *
FROM min_global
JOIN min_by_source USING (id)
Output:
id minPrice minPrice_A minPrice_B
1 1 1 1
2 2 2 3
Consider below option
select * from (
select * except(date),
avg(price) over(partition by id) avgPrice,
min(price) over(partition by id) minPrice
from your_table)
pivot (min(price) minPriceSource for source in ('A', 'B'))
if applied to sample data in your question - output is
The problem is I have over 100 sources and id, if I do query manually the code will be very long. Is there an efficient way to do this?
Use below dynamic version
execute immediate (select '''
select * from (
select * except(date),
avg(price) over(partition by id) avgPrice,
min(price) over(partition by id) minPrice
from your_table)
pivot (min(price) minPriceSource for source in (''' || string_agg(distinct '"' || source || '"') || '''))
'''
from your_table
)

SQL Group By most recent date and sales value

I have the following sales table that displays the customer ID, their name, the order amount, and the order date.
ID
Name
Order
Date
1
A
25
11/10/2006
1
A
10
5/25/2010
1
A
10
6/18/2018
2
B
20
3/31/2008
2
B
15
11/15/2010
3
C
35
1/1/2019
3
C
20
4/12/2007
3
C
10
3/20/2010
3
C
5
10/19/2012
4
D
15
12/12/2013
4
D
15
2/18/2010
5
E
25
12/11/2006
6
F
10
5/1/2016
I am trying to group the data so that for each customer it would only show me their most recent order and the amount, as per below:
ID
Name
Order
Date
1
A
10
6/18/2018
2
B
15
11/15/2010
3
C
35
1/1/2019
4
D
15
12/12/2013
5
E
25
12/11/2006
6
F
10
5/1/2016
So far I've only been able to group by ID and Name, because adding the Order column would also group by that column as well.
SELECT
ID,
Name,
MAX(Date) 'Most recent date'
FROM Table
GROUP BY Customer, Customer
How can I also add the order amount for each Customer?
SELECT ID, Name, Order, Date FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Date DESC) AS sn
FROM your_table_name
) A WHERE sn = 1;
You could use a subqoery for max date
SELECT
ID,
Name,
MAX(Date) 'Most recent date'
FROM Table
GROUP BY Customer, Customer
select a.ID, a.Name, b.max_date
from Table a
inner join (
select name, max(Date) max_date
from Table
group by name
) b on a. name = b.name and a.date = b.max_date
You can use this query to get the expected result:
SELECT S.*
FROM Sales S
CROSS APPLY
(
SELECT ID, Max(Date) MaxDate
FROM Sales
GROUP BY ID
)T
WHERE S.ID = T.ID
AND S.Date = T.MaxDate
ORDER BY S.ID

PostgreSQL Pivot by Last Date

I need to make a PIVOT table from Source like this table
FactID UserID Date Product QTY
1 11 01/01/2020 A 600
2 11 02/01/2020 A 400
3 11 03/01/2020 B 500
4 11 04/01/2020 B 200
6 22 06/01/2020 A 1000
7 22 07/01/2020 A 200
8 22 08/01/2020 B 300
9 22 09/01/2020 B 100
Need Pivot Like this where Product QTY is QTY by Last Date
UserID A B
11 400 200
22 200 100
My try PostgreSQL
Select
UserID,
MAX(CASE WHEN Product='A' THEN 'QTY' END) AS 'A',
MAX(CASE WHEN Product='B' THEN 'QTY' END) AS 'B'
FROM table
GROUP BY UserID
And Result
UserID A B
11 600 500
22 1000 300
I mean I get a result by the maximum QTY and not by the maximum date!
What do I need to add to get results by the maximum (last) date ??
Postgres doesn't have "first" and "last" aggregation functions. One method for doing this (without a subquery) uses arrays:
select userid,
(array_agg(qty order by date desc) filter (where product = 'A'))[1] as a,
(array_agg(qty order by date desc) filter (where product = 'B'))[1] as b
from tab
group by userid;
Another method uses select distinct with first_value():
select distinct userid,
first_value(qty) over (partition by userid order by product = 'A' desc, date desc) as a,
first_value(qty) over (partition by userid order by product = 'B' desc, date desc) as b
from tab;
With the appropriate indexes, though, distinct on might be the fastest approach:
select userid,
max(qty) filter (where product = 'A') as a,
max(qty) filter (where product = 'B') as b
from (select distinct on (userid, product) t.*
from tab t
order by userid, product, date desc
) t
group by userid;
In particular, this can use an index on userid, product, date desc). The improvement in performance will be most notable if there are many dates for a given user.
You can use DENSE_RANK() window function in order to filter by the last date per each product and UserID before applying conditional aggregation such as
SELECT UserID,
MAX(CASE WHEN Product='A' THEN QTY END) AS "A",
MAX(CASE WHEN Product='B' THEN QTY END) AS "B"
FROM
(
SELECT t.*, DENSE_RANK() OVER (PARTITION BY Product,UserID ORDER BY Date DESC) AS rn
FROM tab t
) q
WHERE rn = 1
GROUP BY UserID
Demo
presuming all date values are distinct(no ties occur for dates)

SQL - Group dependant upon type

I've updated the question below as there's a little more complexity to it ...
A question relating to SQL grouping based on type?
I'd like to be able to list the max value for type-A (based on date - per CustID) whilst at the same time listing ALL values for type-b
From this :
Date Ref Type CustID
2019-03-04 123 A 1
2019-03-05 124 A 1
2019-03-06 125 B 3
2019-03-07 126 B 4
2019-03-08 127 B 5
2019-03-06 128 A 2
2019-03-07 129 A 2
2019-03-08 130 A 2
To this :
Date Ref Type CustID
2019-03-05 124 A 1
2019-03-06 125 B 3
2019-03-07 126 B 4
2019-03-08 127 B 5
2019-03-08 130 A 2
Thanks in advance :-)
Is this what you want?
with a as (
select top (1) t.*
from t
where type = 'A'
order by ref desc
)
select a.*
from a
union all
select t.*
from t
where type = 'B';
Or without union all:
select top (1) with ties t.*
from t
order by (case when type = 'B' then 1
else row_number() over (partition by type order by ref desc
end);
use union all
select date,ref,type from table where type='B'
union all
select date,ref,type from table where type='A'
and date = (select max(date) from table where type='A')
Try using union all
select top 1 date,ref, type from tablename
where Type='A' order by date desc
union all
select date,ref, type from tablename
where type='B'
The below query gives you type A records with latest date combined with B records
Select * from
( SELECT Date, Ref, Type
FROM TABLE
WHERE TYPE='A' GROUP BY TYPE
HAVING DATE =MAX(DATE)
UNION
SELECT Date, Ref, Type FROM TABLE
WHERE TYPE='B'
)

sum the values in column for same date and id

I want to add the values in the column cost ,amt- if there is a flag 1 and 2 for same person id on same date. please help. Thank you. Column are:
id date cost amt flag
455 05/25/2013 150 110 1
455 05/25/2013 20 45 2
456 08/17/2013 140 60 1
456 08/17/2013 15 20 2
457 09/28/2013 135 10 1
457 09/28/2013 8 40 2
458 11/09/2013 10 30 1
output should be:
id date cost amt flag
455 05/25/2013 170 155 1
456 08/17/2013 155 80 1
457 09/28/2013 143 50 1
458 11/09/2013 10 30 1
Just for diversity, check out my solution. It uses over (partition by ) for calculation and distinct for filtering out the duplicates.
select distinct o.ID, o.Date,
SUM(o.COST) OVER(PARTITION BY o.ID, o.Date) as cost
,SUM(o.AMT) OVER(PARTITION BY o.ID, o.Date) as amt
,MIN(FLAG) OVER(PARTITION BY o.ID, o.Date) as flag
from orders o
order by o.ID, o.Date
SqlFiddle proof
It's inspired by this article.
Not really sure what you want to do with flag, but you need GROUP BY like:
SELECT id, date, SUM(cost), Sum(amt), 1 as flag
FROM yourTable
GROUP BY id,date
SELECT ID, DATE , SUM(COST), SUM(AMT), MIN(Flag)
FROM TABLE
GROUP BY ID, DATE
If you need flag 1 AND 2 in the same date for the same id then this should work:
SELECT id, date, SUM(cost), SUM(amt) , flag
FROM yourtable a
WHERE flag=1
AND EXISTS (SELECT 1 FROM yourtable b WHERE a.id=b.id AND b.flag=2 AND a.date=b.date)
GROUP BY id, date, flag