Max Aggregate function in Teradata- - teradata

If I have below data :
EMP_ID EMP_DEPT JOIN_DATE END_DATE
1 HR 2/12/2015 8/23/2015
1 HR 4/5/2015 5/20/2015
and have query as:
SELECT emp_id, emp_dept, max(join_date), max(end_date)
FROM emp
GROUP BY 1,2
What will be the output ??

Without group by 1,2 only with group by EMP_ID the O/P would be:- So the query would be:-
SELECT emp_id, emp_dept, MAX(join_date), MAX(end_date)
FROM emp
GROUP BY emp_id, emp_dept;
EMP_ID EMP_DEPT JOIN_DATE END_DATE
1 HR 4/5/2015 8/23/2015

Related

Join unique UserIDs with previous month' first time UserIDs

I want to identify users that had a "first_open" event in month a (here: january) and came back to our in month b (here: february) with an "user_engagement" event.
My idea:
1. Create a table with all users who had a "first_open" event
2. Create a table with all users who had a "user_engagement" event
3. Join both tables on userID
4. Count Users who both had a "first_open" event in month a and month b and count all users from january with the "first_open" event
With the following query I am currently overcounting both the users in month a and b, because I am not counting all unqiue users for both event types.
With
users_first_open as (select
user_pseudo_id,
EXTRACT (Month FROM(DATE(TIMESTAMP_MICROS(user_first_touch_timestamp)))) AS install_month,
event_name as firstopen
FROM
`table.events_*`
where _TABLE_SUFFIX BETWEEN '20190101'
AND '20190108' and event_name = "first_open" and
EXTRACT (Month FROM(DATE(TIMESTAMP_MICROS(user_first_touch_timestamp)))) = 1
),
user_enagement_next_month as (select
user_pseudo_id,
EXTRACT (Month FROM(DATE(TIMESTAMP_MICROS(user_first_touch_timestamp)))) AS engagement_month,
event_name as engagament_next_month
FROM
`table.events_*`
where _TABLE_SUFFIX BETWEEN '20190109'
AND '20190116' and event_name = "user_engagement"
and EXTRACT (Month FROM(DATE(TIMESTAMP_MICROS(user_first_touch_timestamp)))) = 1),
cohort_raw as(
select
user_pseudo_id,
install_month,
engagement_month,
case when firstopen = "first_open" then 1 else 0 end as cohort_count_first_open,
case when engagament_next_month = "user_engagement" then 1 else 0 end as cohort_count_engagement
from
user_enagement_next_month
full join
users_first_open using (user_pseudo_id))--,
select
sum(case when cohort_count_first_open is not null then 1 else 0 end) as users_first_open,
(select sum(case when cohort_count_engagement is not null then 1 else 0 end) as u_engagement_open from cohort_raw where cohort_count_first_open = 1) as users_engagement_open
from cohort_raw
What I tried next was the following: group in table 2 "user_enagement_next_month" by userID, etc.
and create a sum of "first_open" case when and "engagement" case when results. With the later I then included the query to only count users whose count of these two was = 2
-
With
users_first_open as (select
user_pseudo_id,
EXTRACT (Month FROM(DATE(TIMESTAMP_MICROS(user_first_touch_timestamp)))) AS install_month,
event_name as firstopen
FROM
`table.events_*`
where _TABLE_SUFFIX BETWEEN '20190101'
AND '20190131' and event_name = "first_open" and
EXTRACT (Month FROM(DATE(TIMESTAMP_MICROS(user_first_touch_timestamp)))) = 1
),
user_enagement_next_month as (select
user_pseudo_id,
EXTRACT (Month FROM(DATE(TIMESTAMP_MICROS(user_first_touch_timestamp)))) AS engagement_month,
event_name as engagament_next_month
FROM
`table.events_*`
where _TABLE_SUFFIX BETWEEN '20190201'
AND '20190228' and event_name = "session_start"
and EXTRACT (Month FROM(DATE(TIMESTAMP_MICROS(user_first_touch_timestamp)))) = 2
group by 1,2,3)--,
--cohort_raw as(
select
user_pseudo_id,
install_month,
engagement_month,
case when firstopen = "first_open" then 1 else 0 end as cohort_count_first_open,
case when engagament_next_month = "session_start" then 1 else 0 end as cohort_count_engagement
--case when user_pseudo_id is not null then 1 else 0 end as cohort_count_engagement
from
user_enagement_next_month
full join
users_first_open using (user_pseudo_id)),
cohort_agg as (
select *, cohort_count_first_open+cohort_count_engagement as cohort_sum
from cohort_raw
group by 1,2,3,4,5
order by 6 desc)
select
(select count(*) from users_first_open) as cohort_jan,
(select Sum(cohort_sum) from cohort_agg where cohort_sum = 2) as ret,
sum(case when cohort_count_first_open is not null then 1 else 0 end) as users_first_open,
(select sum(case when cohort_count_engagement is not null then 1 else 0 end) as u_engagement_open from cohort_raw where cohort_count_first_open = 1) as users_engagement_open
from cohort_agg
I expect a return rate of around 20%. My output at the moment is 54%, because in my query I am either overcounting or counting to little, because I assume my join does not work.
Maybe I don't clearly understand what you want, but try this one
with
users_first_open as (
select distinct -- is there duplicates for one user_id?
user_pseudo_id,
extract(
month from
timestamp_micros(user_first_touch_timestamp)
) as install_month
from
`table.events_201901*` -- longer prefixes generally perform better
where
_table_suffix between '01' and '31'
and event_name = 'first_open'
and extract(
month from
timestamp_micros(user_first_touch_timestamp)
) = 1
),
user_enagement_next_month as (
select distinct
user_pseudo_id,
extract(
month from
timestamp_micros(user_first_touch_timestamp)
) as engagement_month
from
`table.events_201902*` -- longer prefixes generally perform better
where
_table_suffix between '01' and '28'
and event_name = 'user_engagement'
and extract(
month from
timestamp_micros(user_first_touch_timestamp)
) = 2
)
select
ufo.install_month,
uenm.engagement_month,
count(*) as first_open_event_users_cnt,
count(uenm.user_pseudo_id) as user_engagement_event_users_cnt
from
users_first_open as ufo
left join user_enagement_next_month as uenm
on ufo.user_pseudo_id = uenm.user_pseudo_id
group by
1, 2

Create multiple rows based off a date range

I have a calendar query and a table below. I have a StartDate and end date for a member. Also on my calendar table I have captured a "Weekof" based on the startDate. I would like to capture if a member is active anytime during that weekof. See expected results.
SELECT DISTINCT
--CA.CALENDAR_DATE,
TO_CHAR(CALENDAR_DATE,'MM/DD/YYYY') AS CALENDAR_DATE
TO_CHAR(NEXT_DAY(CALENDAR_DATE, 'Monday') - 7, 'MM/DD/YY-') ||
TO_CHAR(NEXT_DAY(CALENDAR_DATE, 'Monday') - 1, 'MM/DD/YY') AS WEEK_OF_YEAR,
ROW_NUMBER () OVER ( ORDER BY CALENDAR_DATE) AS MasterCalendar_RNK
FROM CALENDAR CA
WHERE 1=1
--AND CA.CALENDAR_DATE BETWEEN ADD_MONTHS(TRUNC(SYSDATE), -12) AND TRUNC(SYSDATE)
--AND CA.CALENDAR_DATE BETWEEN TRUNC(SYSDATE) -5 AND TRUNC(SYSDATE)
ORDER BY TO_DATE(CALENDAR_DATE,'MM/DD/YYYY') DESC
Table
Member StartDate EndDate
A 1/31/17
B 2/1/17 2/15/17
Expected output:
Member StartDate EndDate Week_Of_Year Active
A 1/31/17 1/30/17-2/5/17 1
A 1/31/17 2/6/17-2/12/17 1
A 1/31/17 2/13/17-2/19/17 1
B 2/1/17 2/15/17 1/30/17/2/5/17 1
B 2/1/17 2/15/17 2/6/17-2/12/17 1
B 2/1/17 2/15/17 2/13/17-2/19/17 1
Current Query:
WITH MASTER_CALENDAR AS (
SELECT TRUNC(SYSDATE) + 1 - LEVEL , A.CALENDAR_DATE
FROM (SELECT C.CALENDAR_DATE FROM MST.CALENDAR C WHERE 1=1 AND C.CALENDAR_DATE > SYSDATE-30 AND C.CALENDAR_DATE < SYSDATE) A
WHERE 1=1
CONNECT BY LEVEL <= 1 --NEED TO UPDATE?
ORDER BY A.CALENDAR_DATE DESC
),
ActiveMembers AS (
SELECT H.CLT_CLT_PGMID, H.START_DT
,CASE WHEN TRUNC(H.END_DT) = '1-JAN-3000'
THEN SYSDATE
ELSE TO_DATE(H.END_DT)
END AS END_DT
FROM H
WHERE 1=1
AND H.CLT_CLT_PGMID IN ('1','2','3')
)
SELECT CLT_CLT_PGMID, STARTDATE, ENDDATE, WEEK_OF_YEAR, ACTIVE -- but not week_start
FROM (
SELECT DISTINCT A.CLT_CLT_PGMID,
TO_CHAR(A.START_DT, 'MM/DD/YY') AS STARTDATE,
TO_CHAR(A.END_DT, 'MM/DD/YY') AS ENDDATE,
NEXT_DAY(CAL.CALENDAR_DATE, 'Monday') - 7 AS WEEK_START, -- for ordering later
TO_CHAR(NEXT_DAY(CAL.CALENDAR_DATE, 'Monday') - 7, 'MM/DD/YY-') ||
TO_CHAR(NEXT_DAY(CAL.CALENDAR_DATE, 'Monday') - 1, 'MM/DD/YY') AS WEEK_OF_YEAR,
1 AS ACTIVE
FROM ActiveMembers A
INNER JOIN MASTER_CALENDAR CAL ON CAL.CALENDAR_DATE BETWEEN A.START_DT AND A.END_DT
--BETWEEN TO_CHAR(A.START_DT,'MM/DD/YYYY') AND COALESCE(A.END_DT,(SYSDATE))
)
WHERE 1=1
ORDER BY
CLT_CLT_PGMID , STARTDATE, ENDDATE, WEEK_START
;
Since the calendar query currently generates strings, it would be simpler to go back to the calendar table, join that to your member/date table, and regenerate the week range string:
With CTEs to represent your calendar table (just with dates for the last few weeks for now) and member data:
with calendar(calendar_date) as (
select trunc(sysdate) + 1 - level from dual connect by level <= 42
),
mytable (member, startdate, enddate) as (
select cast('A' as varchar2(6)), date '2017-01-31', cast (null as date) from dual
union all select cast('B' as varchar2(6)), date '2017-02-01', date '2017-02-15' from dual
)
select member, startdate, enddate, week_of_year, active -- but not week_start
from (
select distinct m.member,
to_char(m.startdate, 'MM/DD/YY') as startdate,
to_char(m.enddate, 'MM/DD/YY') as enddate,
next_day(c.calendar_date, 'Monday') - 7 as week_start, -- for ordering later
to_char(next_day(c.calendar_date, 'Monday') - 7, 'MM/DD/YY-') ||
to_char(next_day(c.calendar_date, 'Monday') - 1, 'MM/DD/YY') as week_of_year,
1 as active
from mytable m
join calendar c
on c.calendar_date between m.startdate and coalesce(m.enddate, trunc(sysdate))
)
order by member, startdate, enddate, week_start;
gets
MEMBER STARTDAT ENDDATE WEEK_OF_YEAR ACTIVE
------ -------- -------- ----------------- ----------
A 01/31/17 01/30/17-02/05/17 1
A 01/31/17 02/06/17-02/12/17 1
A 01/31/17 02/13/17-02/19/17 1
A 01/31/17 02/20/17-02/26/17 1
B 02/01/17 02/15/17 01/30/17-02/05/17 1
B 02/01/17 02/15/17 02/06/17-02/12/17 1
B 02/01/17 02/15/17 02/13/17-02/19/17 1
You haven't specified an upper limit for members with no end-date, so I've used today, via coalesce().
The inner query is only needed for ordering, as the week range string can't be used, and you don't want to see the week start on its own; and you can't use distinct and order by a field you aren't selecting.
I'd do this in a similar way to Alex, but slightly different. Seeing as your weeks start with a Monday, I'd use TRUNC(dt, 'iw') to get the ISO start of the week (which happens to be defined as a Monday) for the specified date. Then I'd get the distinct values of those before joining to your table, like so:
with calendar as (select trunc(sysdate) - level + 1 calendar_date
from dual
connect by level <= 50),
your_table as (select 'A' member, date '2017-01-31' startdate, NULL enddate from dual union all
select 'B' member, date '2017-02-01' startdate, date '2017-02-15' enddate from dual)
select yt.member,
yt.startdate,
yt.enddate,
to_char(c.week_start, 'mm/dd/yyyy')
|| ' - ' || to_char(c.week_start + 6, 'mm/dd/yyyy') week_of_year,
1 as active
from your_table yt
inner join (select distinct trunc(cl.calendar_date, 'iw') week_start
from calendar cl) c on c.week_start <= nvl(yt.enddate, SYSDATE) AND c.week_start + 6 >= yt.startdate
order by yt.member,
c.week_start;
MEMBER STARTDATE ENDDATE WEEK_OF_YEAR ACTIVE
------ ---------- ---------- ----------------------- ----------
A 01/31/2017 01/30/2017 - 02/05/2017 1
A 01/31/2017 02/06/2017 - 02/12/2017 1
A 01/31/2017 02/13/2017 - 02/19/2017 1
A 01/31/2017 02/20/2017 - 02/26/2017 1
B 02/01/2017 02/15/2017 01/30/2017 - 02/05/2017 1
B 02/01/2017 02/15/2017 02/06/2017 - 02/12/2017 1
B 02/01/2017 02/15/2017 02/13/2017 - 02/19/2017 1
Like Alex, I've assumed your null enddate runs up until today (sysdate). However, looking at your results for member B, it looks like you're looking for an overlapping range (since 30th Jan is not between 1st and 15th Feb), so I've amended my join clause accordingly. This results in an extra row for member A, so maybe you're wanting to run null enddates up until the previous Sunday of sysdate? Not sure. I'm sure you'll be able to amend that yourself, if you need to.

SQL Server Multiple count dates subselect in same query

I'm trying to figure out a way to pull Order Counts per customer id as well as date of first and last order within a date range from an Orders table where each order has both a buyer_id and seller_id. The Orders table contains OrderNumber, Buyer_ID, Seller_ID, OpenDate, ClosedDate. I can run the following queries individually to achieve my goals, but I would like to have everything in the same query if possible.
Order_Table:
OrderNumber, Buyer_ID, Seller_ID, OpenDate, ClosedDate
Buyer_ID Orders:
select Buyer_ID, COUNT(*)as BuyerOrders
from
(
select Buyer_ID
from Orders
where OpenDate between #StartDate and #EndDate
)
a
group by Buyer_ID
Seller_ID Orders:
select Seller_ID, COUNT(*)as SellerOrders
from
(
select Seller_ID
from Orders
where OpenDate between #StartDate and #EndDate
)
a
group by Seller_ID
Dates of First and Last Order within that range: ??
Any input is greatly appreciated!
Since the result is a union and the same customer_id may have an entry as both buyer and seller, how can I put the information in the same row? My first attempt was to create a temporary table from the result of the Union, but I'm drawing a blank on how to display Buyer OrderCount, Seller OrderCount etc on the same row for each Customer_ID in the resulting table.
select 'Buyer' as Type,
Buyer_ID ID,
Count(*) OrderCount,
Min(OpenDate) FirstOrder,
Max(OpenDate) LastOrder
from Orders
where OpenDate between #StartDate and #EndDate
group by Buyer_ID
union
select 'Seller',
Seller_ID,
Count(*),
Min(OpenDate) FirstOrder,
Max(OpenDate) LastOrder
from Orders
where OpenDate between #StartDate and #EndDate
group by Seller_ID
[EDIT] Yes, a little bit of a cheek accepting my answer, then un-accepting it and changing the question! Anyway, try the following:
;with BuyerFirst (Buyer_ID, RowNum, BuyerCount, OrderID, OpenDate)
As
(select Buyer_ID,
ROW_NUMBER() over (partition by Buyer_ID order by OpenDate, OrderID) as RowNum,
count(*) over (partition by Buyer_ID) As BuyerCount,
OrderID,
OpenDate
from Orders
where OpenDate between #StartDate and #EndDate),
BuyerLast (Buyer_ID, RowNum, OrderID, OpenDate)
As
(select Buyer_ID,
ROW_NUMBER() over (partition by Buyer_ID order by OpenDate Desc, OrderID Desc) as RowNum,
OrderID,
OpenDate
from Orders
where OpenDate between #StartDate and #EndDate),
SellerFirst (Seller_ID, RowNum, SellerCount, OrderID, OpenDate)
As
(select Seller_ID,
ROW_NUMBER() over (partition by Seller_ID order by OpenDate, OrderID) as RowNum,
count(*) over (partition by Buyer_ID) As SellerCount,
OrderID,
OpenDate
from Orders
where OpenDate between #StartDate and #EndDate),
SellerLast (Seller_ID, RowNum, OrderID, OpenDate)
As
(select Seller_ID,
ROW_NUMBER() over (partition by Seller_ID order by OpenDate Desc, OrderID Desc) as RowNum,
OrderID,
OpenDate
from Orders
where OpenDate between #StartDate and #EndDate)
select c.*,
bf.BuyerCount,
bf.OpenDate As BuyerFirstOrderDate,
bf.OrderID As BuyerFirstOrderID,
bl.OpenDate As BuyerLastOrderDate,
bl.OrderID As BuyerLastOrderID,
sf.SellerCount,
sf.OpenDate As SellerFirstOrderDate,
sf.OrderID As SellerFirstOrderID,
sl.OpenDate As SellerLastOrderDate,
sl.OrderID As SellerLastOrderID
from Customers c
left join BuyerFirst bf on c.CustomerID = bf.Buyer_ID and bf.RowNum = 1
left join SellerFirst sf on c.CustomerID = sf.Seller_ID and sf.RowNum = 1
left join BuyerLast bl on c.CustomerID = bl.Buyer_ID and bl.RowNum = 1
left join SellerLast sl on c.CustomerID = sl.Seller_ID and sl.RowNum = 1

linq to sql: 2 counts as result

I want to do the following in LINQ to SQL:
Select count(*) as count_1,
(select count(*) from tableName2) as count_2 FROM tableName
Where x = y
The result should be
Column 1 | column 2
--------------------
50 34
What you need to do is something like this:
select
(select count(*)
from tableName
where x = y) as count_1,
(select count(*)
from tableName2) as count_2

Group by function column

I'm writing a query like this...
select to_char(e_date, 'MON/YYYY') as Month , location_code, count(employee_number) from...
Now I want to group by Month and Location_code. so how to use to_char(e_date, 'MON/YYYY') as Month in group by clause?
EDIT:
select to_char(vheda.e_date, 'MON/YYYY') as Months , hla.location_code, count(vheda.employee_number) emp_count from
virtu.virt_hr_emp_daily_attendance vheda
inner join per_all_people_f papf on vheda.party_id = papf.party_id
inner join per_all_assignments_f paaf on papf.person_id = paaf.person_id
inner join hr_locations_all hla on paaf.location_id = hla.location_id
where (trunc(sysdate) between PAPF.EFFECTIVE_START_DATE and PAPF.EFFECTIVE_END_DATE)
--and (vheda.e_in_time is not null)
and vheda.e_duration <> 0
and (trunc(sysdate) between PAAF.EFFECTIVE_START_DATE and PAAF.EFFECTIVE_END_DATE)
and vheda.e_date between '1-aug-2014' and '31-oct-2014'
group by hla.location_code, vheda.e_date
order by vheda.e_date
OUT PUT WHEN USE GROUP BY CLAUSE group by to_char(vheda.e_date, 'MON/YYYY'), hla.location_code:
ORA-00979: not a GROUP BY expression
00979. 00000 - "not a GROUP BY expression"
*Cause:
*Action:
Error at Line: 58 Column: 37
select to_char(e_date, 'MON/YYYY') as Month , location_code, count(employee_number)
from ...
group by to_char(e_date, 'MON/YYYY'), location_code
You need to group by To_char(vheda.e_date, 'MON/YYYY') and hla.location_code.
SELECT To_char(vheda.e_date, 'MON/YYYY') AS Months,
hla.location_code,
Count(vheda.employee_number) emp_count
FROM virtu.virt_hr_emp_daily_attendance vheda
inner join per_all_people_f papf
ON vheda.party_id = papf.party_id
inner join per_all_assignments_f paaf
ON papf.person_id = paaf.person_id
inner join hr_locations_all hla
ON paaf.location_id = hla.location_id
WHERE ( Trunc(SYSDATE) BETWEEN PAPF.effective_start_date AND
PAPF.effective_end_date )
--and (vheda.e_in_time is not null)
AND vheda.e_duration <> 0
AND ( Trunc(SYSDATE) BETWEEN PAAF.effective_start_date AND
PAAF.effective_end_date )
AND vheda.e_date BETWEEN '1-aug-2014' AND '31-oct-2014'
GROUP BY To_char(vheda.e_date, 'MON/YYYY'),
hla.location_code
ORDER BY vheda.e_date
For example, let's see the same with EMP table,
SQL> SELECT To_char(hiredate, 'MON/YYYY') AS Months,
2 deptno,
3 Count(empno) emp_count
4 FROM emp
5 GROUP BY To_char(hiredate, 'MON/YYYY'),
6 deptno
7 /
MONTHS DEPTNO EMP_COUNT
-------- ---------- ----------
DEC/1980 20 1
JUN/1981 10 1
NOV/1981 10 1
MAY/1987 20 1
FEB/1981 30 2
MAY/1981 30 1
DEC/1981 30 1
JAN/1982 10 1
SEP/1981 30 2
DEC/1981 20 1
APR/1981 20 1
APR/1987 20 1
12 rows selected.
SQL>
select EXTRACT(MONTH FROM e_date)||'/'|| EXTRACT(Year FROM e_date) as months , location_code, count(employee_number)
FROM ...
group by EXTRACT(MONTH FROM e_date)||'/'|| EXTRACT(Year FROM e_date), location_code
You can also use EXTRACT function in GROUP BY clause..
i hope it helps..

Resources