Starting each SQL record from a specific point - sql

I am wanting to figure out how to start each record from a specific point in SQL. I have created a data set to try and represent what I would like.
This is the starting data set.
However, I want to get a new view, with a defined starting point.
So each member record starts from ID 33 onwards, ordered by Member and Date. Basically want every record after ID 33 and the corresponding date for it.

If your ids are in order, you can use:
select t.*
from t
where id >= 33
order by member, date;
If the ids are not in order, one method is a correlated subquery:
select t.*
from t
where date >= (select min(t2.date) from t t2 where t2.member = t.member and t2.id = 33);
And finally, a windows function approach is:
select t.*
from (select t.*,
min(case when id = 33 then date end) over (partition by member) as date_33
from t
) t
where date >= date_33;

Related

How create a unique ID based on conditions in SQL?

I would like to get a new ID, no matter the format (in the example below 11,12,13...)
Based on the following condition:
Every time the days column value is greater then 1 and not null then current row and all following ones will get the same ID until a new value will meet the condition.
Within the same email
Below you can see the expected 1 (in the format of XX)
I thought about using two conditions with the following order between them
Every time the days column value is greater then 1 then all following rows will get the same ID until a new value will meet the condition.
2.AND When lag (previous) is equal to 0/1/null.
Assuming you have an EmailDate column over which you're ordering (a DATETIME field, really), try something like this:
WITH
TableNameWithEmailDateIDs AS (
SELECT
*,
ROW_NUMBER() OVER (
ORDER BY
Email DESC,
EmailDate
) AS EmailDateID
FROM
TableName
),
IDs AS (
SELECT
*,
LEAD(EmailDateID, 1) OVER (
ORDER BY
Email,
EmailDate
) AS LeadEmailDateID
FROM
(
SELECT
*,
-- REMOVE +10 if you don't want 11 to be starting ID
ROW_NUMBER() OVER (
ORDER BY
Email DESC,
EmailDate
)+10 AS ID
FROM
TableNameWithEmailDateIDs
WHERE
Days > 1
OR Days IS NULL
) X
)
SELECT
COALESCE(TableName.EmailDate, IDs.EmailDate) AS EmailDate,
IDs.Email,
COALESCE(TableName.Days, IDs.Days) AS Days,
IDs.ID
FROM
IDs
LEFT JOIN TableNameWithEmailDateIDs TableName
ON IDs.Email = TableName.Email
AND TableName.EmailDateID BETWEEN
IDs.EmailDateID
AND IDs.LeadEmailDateID-1
ORDER BY
ID DESC,
TableName.EmailDate DESC
;
First, create a CTE that generates IDs for each distinct Email/Date combo (helpful for LEFT JOIN condition later). Then, create a CTE that generates IDs for rows that meet your condition (i.e. the important rows). Finally, LEFT JOIN your main table onto that CTE to fill in the "gaps", so to speak.
I suggest running each of the components of this query independently to fully understand what's going on.
Hope it helps!

SQL: Extracting row segment pertaining to maximum value of a column for each unique entity in some other column

I have ‘Input Table’ as shown in attached snapshot.
Using SQL, I am intending to build an ‘Output Table’ where:
‘MaxDays’: should show the maximum value of ‘Days’ for a given ‘ID’
‘Type_MaxDays’: is the corresponding value of ‘Type’ pertaining to the maximum ‘Days’ identified for ‘MaxDays’
‘TotalUniqueType’: Counts all the unique ‘Type’ for any given ID
For example, for ID=878, Days=90 is the maximum of (63, 90, 33, 48) and it corresponds to Type=A. Hence, in output table, Max_Days= 90 and Type_MaxDays= A. Since ID=878 has total 4 unique 'Type' (ie.. A, B, C, D) so TotalUniqueType=4.
Finding the ‘TotalUniqueType’ seems straightforward, however coming from a python/pandas background, I am not able to figure out how to retrieve ‘MaxDays’ and ‘Type_MaxDays’ using SQL. Please advise.
I would recommend window functions and aggregation:
select id,
max(days) as maxdays,
max(case when seqnum = 1 then type end) as type_at_maxdays,
count(distinct type)
from (select t.*,
row_number() over (partition by id order by days desc) as seqnum
from t
) t
group by id;
One option would be to join to a subquery which finds, for each ID, the maximum number of days along with the distinct type count. Then, also select the type of the row having the maximum number of days.
SELECT
t1.ID,
t1.Days AS MaxDays,
t1.Type AS Type_MaxDays,
t2.TypeCnt AS TotalUniqueType
FROM yourTable t1
INNER JOIN
(
SELECT ID, MAX(Days) AS MaxDays, COUNT(DISTINCT Type) AS TypeCnt
FROM yourTable
GROUP BY ID
) t2
ON t1.ID = t2.ID AND t1.Days = t2.MaxDays;
Demo

Need to find a difference of data from the same table in hive

I have a history table with loaded timestamp column. I need to fetch the subtracted data using the timestamp column.
Logic:To get the email address by subtracting data from (loaded_timestamp -1)and current_timestamp.Only the subtracted data should be the output.
Select query :
select t1.email_addr
from (select *
from table t1
where loaded_timestamp = current_timestamp
) left outer join
(select *
from table t2
where loaded_timestamp = date_sub(current_timestamp,1)
)
where t1.email!=t2.email;
Table has following columns
Email address, First name , last name, loaded_timestamp.
xxx#gmail.com,xxx,aaa,2020-03-08.
yyy#gmail.com,yyy,bbb,2020-03-08.
zzz#gmail.com,zzz,ccc,2020-03-08.
xxx#gmail.com,xxx,aaa,2020-03-09.
yyy#gmail.com,yyy,bbb,2020-03-09.
Desired Result
zzz#gmail.com
So if subtract the two dates from the same table i.e (2020-03-09 - 2020-03-08 ). I should get only the record which is not matching . Matching records should be discarded and unmatched record should be the output.
The best I can figure out is that you want emails that appear only once. If that is the case, use window functions:
select t.*
from (select t.*, count(*) over (partition by email) as cnt
from t
) t
where cnt = 1;
If you want emails in the data but not loaded on the current date, then:
select t.email
from t
group by t.email
having max(timestamp) <> current_date;

SQL Developer - Days between two specific records

https://i.stack.imgur.com/3vREY.jpg
I have included an example in above link. Can you assist with helping me find the days between each ID IF the TYPE is 'C' and the TYPE_ID is 123?
For example -- The number of days between ID 313031 is 1,146 days (between 2/20/2018 and 1/1/2015) since we would be ignoring the other ID because it has a TYPE A.
First you have to determine the records you want compared. You could for instance use MIN(date) and MAX(date), but this really depends on your data.
Next, to determine the difference you can simply subtract the dates
So for instance, assuming you want to compare the first and last date for a given ID:
Select ID,
Min(Date),
MAX(Date),
Min(Date) - MAX(Date) as difference_in_days
From your_table
WHERE TYPE = 'C' and TYPE_ID = 123
GROUP BY ID
this will work :
select id,max1-min1 from (select max(date) as max1,min(date) as min1,id from tablename
where type='C' group by id )

Microsoft Access 2010: Select most recent max Record ID for each LANID

I need to filter out this data based on some criteria.
For every unique LANID, a user can have up to 2 records. Some users will only have 1 record.
I need to select the max Record ID for each LANID.
So create one query to determine the max(recordID) when grouped by LANID, then a second query using the first as the datasource joining it back to your table on LANID and max(recordID)
Assuming the last update date is not duplicated for a given row, then one method is to use a correlated subquery to get the last date and then get the rest of the columns in the row:
select sd.*
from sampleData as sd
where sd.RecordId = (select max(sd2.RecordId)
from sampleData as sd2
where sd2.lanId = sd.lanId
);
EDIT:
If you wanted the largest record id for the most recent update date:
select sd.*
from sampleData as sd
where sd.RecordId = (select top 1 sd2.RecordId
from sampleData as sd2
where sd2.lanId = sd.lanId
order by sd2.lastUpdateDate desc, sd2.RecordId desc
);