Select rows from a particular row to latest row if that particular row type exist - sql

I want to achieve these two requirements using a single query. Currently I'm using 2 queries in the program and use C# to do the process part something like this.
Pseudocode
select top 1 id from table where type=b
if result.row.count > 0 {var typeBid = row["id"]}
select * from table where id >= {typeBid}
else
select * from table
Req1: If there is records exist with type=b, Result should be latest row with type=b and all other rows added after.
Table
--------------------
id type date
--------------------
1 b 2021-10-15
2 a 2021-11-16
3 b 2021-11-19
4 a 2021-12-02
5 c 2021-12-12
6 a 2021-12-16
Result
--------------------
id type date
--------------------
3 b 2021-11-19
4 a 2021-12-02
5 c 2021-12-12
6 a 2021-12-16
Req2: There is NO record exist with type=b. Query should select all the records in the table
Table
---------------------
id type date
---------------------
1 a 2021-10-15
2 a 2021-11-16
3 a 2021-11-19
4 a 2021-12-02
5 c 2021-12-12
6 a 2021-12-16
Result
--------------------
id type date
--------------------
1 a 2021-10-15
2 a 2021-11-16
3 a 2021-11-19
4 a 2021-12-02
5 c 2021-12-12
6 a 2021-12-16

with max_b_date as (select max(date) as date
from table1 where type = 'b')
select t1.*
from table1 t1
cross join max_b_date
where t1.date >= max_b_date.date
or max_b_date.date is null
(table is a SQL reserved word, https://en.wikipedia.org/wiki/SQL_reserved_words, so I used table1 as table name instead.)
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=bd05543a9712e27f01528708f10b209f

Please try this(It's somewhat deep but might you exact looking for)
select ab.* from
((select top 1 id, type, date from test where type = 'b' order by id desc)
union
select * from test where type != 'b') as ab
where ab.id >= (select COALESCE((select top 1 id from test where type = 'b' order by id desc), 0))
order by ab.id;
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=739eb6bfee787e5079e616bbf4e933b1

Looks Like you can use an OR condition here
SELECT
*
FROM
(
SELECT
*,
BCount = COUNT(CASE type WHEN 'B' THEN 1 ELSE NULL END)-- to get the Count of Records with Type b.
FROM Table
)Q
WHERE
(
BCount > 0 AND id >= (select top 1 id from table where type=b)-- if there are Row's with Type b then select Req#1
)
OR
(
BCount = 0 -- if THere are no rows with Type B select All
)

Related

Select rows with max date from table

I have such table and need table 2 result. I am trying to select rows with max date grouped by project_id and ordered by id. And result table must have id column. Tried such request:
SELECT MAX(charges.id) as id,
"charges"."profile_id", MAX(failed_at) AS failed_at
FROM "charges"
GROUP BY "charges"."profile_id"
ORDER BY "charges"."id" ASC
And have error:
ERROR: column "charges.id" must appear in the GROUP BY clause or be used in an aggregate function)
Example table
id
profile_id
failed_at
1
1
01.01.2021
2
1
01.02.2021
3
1
01.03.2021
4
2
01.06.2021
5
2
01.05.2021
6
2
01.04.2021
Needed result
id
profile_id
failed_at
3
1
01.03.2021
4
2
01.06.2021
SELECT charges.*
FROM charges
INNER JOIN
(
SELECT
profile_id,
MAX(charges.failed_at) AS MaxFailed_at
FROM charges
GROUP BY profile_id
) AS xQ ON charges.profile_id = xQ.profile_id AND charges.failed_at = xQ.MaxFailed_at

Retrieving last record in each group from database with order by

There is a table ticket that contains data as shown below:
Id Impact group create_date
------------------------------------------
1 3 ABC 2020-07-28 00:42:00.0
1 2 ABC 2020-07-28 00:45:00.0
1 3 ABC 2020-07-28 00:48:00.0
1 3 ABC 2020-07-28 00:52:00.0
1 3 XYZ 2020-07-28 00:55:00.0
1 3 XYZ 2020-07-28 00:59:00.0
Expected result:
Id Impact group create_date
------------------------------------------
1 3 ABC 2020-07-28 00:42:00.0
1 2 ABC 2020-07-28 00:45:00.0
1 3 ABC 2020-07-28 00:52:00.0
1 3 XYZ 2020-07-28 00:59:00.0
At present, this is the query that I use:
WITH final AS (
SELECT p.*,
ROW_NUMBER() OVER(PARTITION BY p.id,p.group,p.impact
ORDER BY p.create_date desc, p.impact) AS rk
FROM ticket p
)
SELECT f.*
FROM final f
WHERE f.rk = 1
Result, i am getting is:
Id Impact group create_date
-----------------------------------------
1 2 ABC 2020-07-28 00:45:00.0
1 3 ABC 2020-07-28 00:52:00.0
1 3 XYZ 2020-07-28 00:59:00.0
it seems that partition by is getting precedence over order by values. is there other way to achieve expected result. I am running these queries on amazon Redshift.
You could use LEAD() to check if the Impact changes between rows, taking only the rows where the value will change.
WITH
look_forward AS
(
SELECT
*,
LEAD(impact) OVER (PARTITION BY id, group ORDER BY create_date) AS lead_impact
FROM
ticket
)
SELECT
*
FROM
look_forward
WHERE
lead_impact IS NULL
OR lead_impact <> impact
You seem to want rows where id/impact/group change relative to the next row. A simple way is to look at the next create_date overall and the next create_date for the group. If these are the same, then filter:
select t.*
from (select t.*,
lead(create_date) over (order by create_date) as next_create_date,
lead(create_date) over (partition by id, impact, group order by create_date) as next_create_date_img
from ticket t
) t
where next_create_date_img is null or next_create_date_img <> next_create_date;

Group by in SQL returning error: Selected non-aggregate values must be part of the associated group

I have a table that looks like this:
date store flag
1 5/4/2018 a 1
2 5/4/2018 a 1
3 5/3/2018 b 1
4 5/3/2018 b 0
5 5/2/2018 a 1
6 5/2/2018 b 0
I want to group by date and store and sum the number of flags
i.e. table_a below:
date store total_flag
1 5/4/2018 a 2
3 5/3/2018 b 1
4 5/2/2018 a 1
5 5/2/2018 b 0
This is what I'm trying:
create multiset volatile table flag_summary as (
sel table_a.*, SUM(table_a.flag) as total_flag
group by date, store
)
with data primary index (date, store) on commit preserve rows;
The above gives me an error, "CREATE TABLE Failed. [3504] Selected non-aggregate values must be part of the associated group.
You are selecting all of tableA (including the flag). You should just be pulling the date and the store since you want the sum of the flag.
SELECT date, store, SUM(flag)
FROM tableA
GROUP BY date, store

SQL select combine data from multiple rows into a single row

I have a table that looks similar to this:
ID OLD NEW TIME
1 a b 5
1 b c 7
1 c d 45
1 d e 4
2 a b 1
2 b d 8
2 d e 45
3 b c 15
3 c d 14
And I would like to build a report that looks like this (basically for each OLD data point grab the TIME value):
ID TimeForA TimeForB TimeForC TimeForD
1 5 7 45 4
2 1 8 NULL 45
3 NULL 15 14 NULL
I have been able to get all the data into the correct columns, but have not been able to combine each row into a single row for each ID. My current query looks like this (no I don't have every column in place yet, still just testing):
WITH CTE (id, ATime, BTime)
AS
(
select T1.oid, T1.loggedFor, null, T1.time as Atime
from Table1 T1
where T1.OLD = 'a'
union
select T1.oid, T1.loggedFor, T1.time as BTime, null
from Table1 T1
where T1.old = 'b'
)
select ID, ATime, BTime
from CTE
order by ID
Any help appreciated!
Try this:
select id,
sum(if(old = 'a',time,null)) as time_for_a,
sum(if(old = 'b',time,null)) as time_for_b,
sum(if(old = 'c',time,null)) as time_for_c,
sum(if(old = 'd',time,null)) as time_for_d
from test_tbl
group by id
order by id;

sql show distinct column

I have a table like this and need to add column which will show info only in distinct rows:
ID Name
1 1001
2 1001
3 1001
4 1001
5 1002
6 1002
7 1002
8 1003
9 1004
10 1004
I need such result:
ID Name Result
1 1001 1
2 1001 NULL
3 1001 NULL
4 1001 NULL
5 1002 1
6 1002 NULL
7 1002 NULL
8 1003 1
9 1004 1
10 1004 NULL
The result column basically selects 1 only for distinct Name values.
This should be some basic query, but I cannot figure it.
Since ordering will wreak havoc with your concept, I'll assume that you'll always sort by ID.
You can do something like this:
select ID, Name,
case (select count(*) from table t2 where t2.Name=t1.Name and t1.ID > t2.ID)
when 0 then 1
else null
end as Result
from table t1
This will count all the rows with the same name, and with a lower ID than the row processed. If there are no such rows, then it's a new name, so it'll get the 1, otherwise, it will get a null value.
You can use row_number to get the first instance of a group, in this case Name:
select ID, Name,
case row_number() over(partition by Name order by ID)
when 1 then 1 end Result
from YourTable
Try that
SELECT ID,
NAME,
Case When x.minId Is Not Null Then 1 Else Null End As Result
FROM Table
left JOIN (
SELECT Name, min(id) minId
FROM Table ) x
on x.minId = Table.Id
and x.Name = Table.Name