rank function in Teradata [closed] - sql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
I'm trying to use the rank function and failing, could you guys give me some help?
here you can see some tries:
SELECT DBB.OBJECTDATABASENAME,
DBB.OBJECTTABLENAME,
DBB.objecttype AS TABLEKIND,
DBB.LOGDATE,
DBG.STATEMENTTYPE,
rank(DBB.OBJECTDATABASENAME, DBB.OBJECTTABLENAME, DBB.objecttype desc) as row_rank
--rank() over (order by DBB.OBJECTTABLENAME desc) as row_rank
--rank() over (order by DBB.OBJECTDATABASENAME, DBB.OBJECTTABLENAME, DBB.objecttype desc) as row_rank
FROM PDCRINFO.DBQLOBJTBL_HST_v1620 DBB
LEFT JOIN PDCRINFO.DBQLogTbl_HsT_v1620 DBG
ON DBG.QUERYID = DBB.QUERYID
AND DBG.LOGDATE = DBB.LOGDATE
AND DBG.PROCID = DBB.PROCID
LEFT JOIN PDCRINFO.DBQLSQLTBL_HST QRY
ON QRY.LOGDATE = DBB.LOGDATE
AND QRY.QUERYID = DBB.QUERYID
AND QRY.PROCID = DBB.PROCID
WHERE DBB.LOGDATE = ('2022-11-27')
AND DBB.OBJECTTYPE IN ('Tab', 'Viw')
GROUP BY 1,2,3,4,5;
This is what I'm getting from my tries:
OBJECTDATABASENAME OBJECTTABLENAME TABLEKIND LOGDATE STATEMENTTYPE row_rank
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 1
PM_MSTRDB STATUS_SUBPRODUTO_T Tab 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_T Tab 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_T Tab 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_T Tab 27/11/2022 Select 1
PM_EXP1DB STATUS_ACCUNT_CLI_V Viw 27/11/2022 Select 1
PM_EXP1DB STATUS_ACCUNT_CLI_V Viw 27/11/2022 Select 1
And here the outuput I'm looking for:
OBJECTDATABASENAME OBJECTTABLENAME TABLEKIND LOGDATE STATEMENTTYPE row_rank
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 2
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 3
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 4
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 5
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 6
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 7
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 8
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 9
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 10
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 11
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 12
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 13
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Select 14
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 1
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 2
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 3
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 4
PM_MSTRDB STATUS_SUBPRODUTO_V Viw 27/11/2022 Update 5
PM_MSTRDB STATUS_SUBPRODUTO_T Tab 27/11/2022 Select 1
PM_MSTRDB STATUS_SUBPRODUTO_T Tab 27/11/2022 Select 2
PM_MSTRDB STATUS_SUBPRODUTO_T Tab 27/11/2022 Select 3
PM_MSTRDB STATUS_SUBPRODUTO_T Tab 27/11/2022 Select 4
PM_EXP1DB STATUS_ACCUNT_CLI_V Viw 27/11/2022 Select 1
PM_EXP1DB STATUS_ACCUNT_CLI_V Viw 27/11/2022 Select 2
As you can see, the key (OBJECTDATABASENAME,OBJECTTABLENAME,objecttype,LOGDATE,STATEMENTTYPE) for the selected values mentioned in the where clause, returns 14 rows, and I want to enumerate these 14 rows.

Documentation says
A rank r implies the existence of exactly r-1 rows with sort_expression value preceding it. All rows having the same sort_expression value are assigned the same rank.
That happened in your case - all rows share the same rank: 1.
Did you try row_number instead?
select ...,
row_number() over (order by DBB.OBJECTDATABASENAME, DBB.OBJECTTABLENAME, DBB.objecttype desc) rn
from ...
See (the same) documentation page; it explains row_number as well. Maybe you'll also need to include the partition by clause; can't tell.
You commented:
I want to know is, for a key, how many row I have, and this for each key.
Isn't that the count function, then? Could be aggregation, or you could use its analytic form (I guess that's what you're looking for), e.g.
select ...
count(*) over (partition by dbb.objectdatabasename)
from ...
(I don't know what "each key" actually means; maybe you should add additional columns into the partition by clause, or ...).

Related

Sql server remove duplicate and display latest data based on parameters

I have the following two tables: First is the result of my query, and the second one is the result that I want to achieve. I need help in displaying all the lastest data based on the transaction date for each concessionaire.
ConcessionaireId EndReading TransactionDate
1 3606 9/1/2022
1 3586 8/1/2022
1 3565 7/1/2022
2 4174 9/1/2022
2 4163 8/1/2022
2 4151 7/1/2022
3 7125 9/1/2022
3 7090 8/1/2022
3 7051 7/1/2022
4 6019 9/1/2022
4 5992 8/1/2022
4 5963 7/1/2022
5 3165 9/1/2022
5 3151 8/1/2022
5 3139 7/1/2022
ConcessionaireId EndReading TransactionDate
1 3606 9/1/2022
2 4174 9/1/2022
3 7125 9/1/2022
4 6019 9/1/2022
5 3165 9/1/2022
SELECT top 100 percent
ConcessionaireId, EndReading, FORMAT(TransactionDate, 'MM/dd/yyyy') AS 'TransactionDate'
FROM Transactions
WHERE EXISTS (SELECT * FROM Transactions
GROUP BY ConcessionaireId, Particulars)
AND ConcessionaireId IS NOT NULL AND Particulars = 'Billing'
GROUP BY ConcessionaireId, EndReading, TransactionDate
HAVING ConcessionaireId > 0
ORDER BY ConcessionaireId, MAX(CONVERT(int,(FORMAT(TransactionDate,'yyyyMMdd')))) DESC
You can achieve this using ROW_NUMBER() Window function in SQL server
;With CTE AS(
SELECT top 100 percent
ConcessionaireId, EndReading, FORMAT(TransactionDate, 'MM/dd/yyyy') AS 'TransactionDate',
ROW_NUMBER() OVER(PARTITION BY ConcessionaireId ORDER BY TransactionDate DESC) AS RN
FROM Transactions
WHERE EXISTS (SELECT * FROM Transactions
GROUP BY ConcessionaireId, Particulars)
AND ConcessionaireId IS NOT NULL AND Particulars = 'Billing'
GROUP BY ConcessionaireId, EndReading, TransactionDate
HAVING ConcessionaireId > 0
ORDER BY ConcessionaireId, MAX(CONVERT(int,(FORMAT(TransactionDate,'yyyyMMdd')))) DESC)
SELECT ConcessionaireId, EndReading, TransactionDate
FROM CTE
WHERE RN = 1
ORDER BY ConcessionaireId

Matching previous and current records WITH and WITHOUT LAG and LEAD

I have table like below. Records do not have any primary key and I want to achieve it both WITH and WITHOUT LAG and LEAD function.
ID ENTID INOUTDATE YEAR MONTH STATUS
1923 1923 [NULL] 2099 12 Out
1923 10690 [NULL] 2099 12 Out
1923 9670 2012-08-24 00:00:00 2012 8 In
1923 1923 2013-06-01 00:00:00 2013 6 In
1923 9670 2018-04-19 00:00:00 2018 4 Out
1923 10690 2019-02-01 00:00:00 2019 2 In
And I want to get the records as per below.
ID ENTID INOUTDATE YEAR MONTH STATUS
1923 10690 [NULL] 2099 12 Out
1923 9670 2012-08-24 00:00:00 2012 8 In
1923 9670 2018-04-19 00:00:00 2018 4 Out
1923 10690 2019-02-01 00:00:00 2019 2 In
lag() is the simplest method:
select t.*
from (select t.*,
lag(status) over (partition by id, (case when inoutdate is null then 1 else 2 end)
order by inoutdate
) as prev_status
from t
) t
where prev_status is null or prev_status <> status;
You can treat this as a group-and-islands problem, identifying the islands using row_number(). The logic is more complicated:
select t.*
from (select t.*,
row_number() over (partition by id, (case when inoutdate is null then 1 else 2 end), status, (seqnum - seqnum_s)
order by inoutdate
) as seqnum_g
from (select t.*,
row_number() over (partition by id, (case when inoutdate is null then 1 else 2 end) order by inoutdate) as seqnum,
row_number() over (partition by id, (case when inoutdate is null then 1 else 2 end), status order by inoutdate) as seqnum_s
from t
) t
) t
where seqnum_g = 1;

Oracle SQL query to get Weekly Records

I have oracle database table 'my_table' with few sample rows as following-
Case_ID Start_Date End_Date STATUS
123 01/10/2018 03/10/2018 Close
124 02/10/2018 Open
125 03/10/2018 05/10/2018 Close
126 04/10/2018 Open
127 05/10/2018 07/10/2018 Close
128 06/10/2018 Open
129 07/10/2018 09/10/2018 Close
130 08/10/2018 10/10/2018 Close
131 09/10/2018 Open
I want to get output in following format -
Week_No Inflow Outflow Total_Backlog
40 7 4 3
41 2 1 4
How to combine following three queries to get the desired output in above format using one query?
SELECT to_char(Start_Date,'IW') Week_No, count(CASE_ID) as Inflow
FROM my_table;
SELECT to_char(End_Date,'IW') Week_No, count(CASE_ID) as Outflow
FROM my_table
WHERE status='Close';
SELECT to_char(Start_Date,'IW') Week_No, count(CASE_ID) as Total_Backlog
FROM my_table
WHERE status <> 'Close';
You might use:
select week_no, sum(nvl(Inflow,0)) as Inflow,
sum(nvl(Outflow,0)) as Outflow,
sum(nvl(Total_Backlog,0)) as Total_Backlog
from
(
select to_char(Start_Date,'IW') Week_No,
count(CASE_ID) as Inflow,
( case when STATUS != 'Close' then count(CASE_ID) end ) as Total_Backlog,
null Outflow
from my_table
group by to_char(Start_Date,'IW'), status
union all
select to_char(End_Date,'IW') Week_No,
null as Inflow, null as Total_Backlog,
( case when STATUS = 'Close' then count(CASE_ID) end ) as Outflow
from my_table
where End_Date is not null
group by to_char(End_Date,'IW'), status
)
group by week_no
order by week_no;
WEEK_NO INFLOW OUTFLOW TOTAL_BACKLOG
40 7 3 3
41 2 2 1
Rextester Demo
or you may prefer in a little different way as :
select week_no, sum(nvl(Inflow,0)) as Inflow,
sum(nvl(Outflow,0)) as Outflow,
sum(nvl(Total_Backlog,0)) as Total_Backlog
from
(
select to_char(Start_Date,'IW') Week_No,
count(CASE_ID) as Inflow,
count( case when STATUS != 'Close' then CASE_ID end ) as Total_Backlog,
null Outflow
from my_table
group by to_char(Start_Date,'IW')
union all
select to_char(End_Date,'IW') Week_No,
null as Inflow, null as Total_Backlog,
count( case when STATUS = 'Close' then CASE_ID end ) as Outflow
from my_table
where End_Date is not null
group by to_char(End_Date,'IW')
)
group by week_no
order by week_no;
WEEK_NO INFLOW OUTFLOW TOTAL_BACKLOG
40 7 3 3
41 2 2 1

Query - Latest date from other table and the linked data

n_station
code_stas nom_station
1 StationA
2 StationB
3 StationC
val_horaire
code_mesure date_val_hor h_01 h_02 h_03
1 14/11/2016 23 29 32
1 15/11/2016 45 47 35
2 14/11/2016 12 15 13
2 15/11/2016 21 23 19
3 14/11/2016 74 75 79
I would like to get the latest (date) row of the table val_horaire and join it with table n_station
Result
cod_stas nom_station date_val_hor h_01 h_02 h_03
1 StationA 15/11/2016 45 47 35
2 StationB 15/11/2016 21 23 19
3 StationC 14/11/2016 74 75 79
How can I achieve this ? The following query does not work
SELECT st.code_stas, st.nom_station, max(vh.date_val_hor), vh.h_01, vh.h_02, vh.h_03
FROM n_station st
INNER JOIN val_horaire vh
ON st.code_stas = vh.code_mesure
GROUP BY st.code_stas, st.nom_station, vh.h_01, vh.h_02, vh.h_03
This will show me multiple times a station
Solution No.1:
SELECT
st.code_stas,
st.nom_station,
MAX(vh.date_val_hor) KEEP(DENSE_RANK FIRST ORDER BY st.nom_station DESC) AS date_val_hor,
MAX(vh.h_01) KEEP(DENSE_RANK FIRST ORDER BY st.nom_station DESC) AS h_01,
MAX(vh.h_02) KEEP(DENSE_RANK FIRST ORDER BY st.nom_station DESC) AS h_02,
MAX(vh.h_03) KEEP(DENSE_RANK FIRST ORDER BY st.nom_station DESC) AS h_03
FROM
n_station st,
val_horaire vh
WHERE
st.code_stas = vh.code_mesure
GROUP BY st.code_stas, st.nom_station
Solution No.2:
SELECT code_stas, nom_station, h_01, h_02, h_03 FROM (
SELECT
st.code_stas,
st.nom_station,
vh.date_val_hor,
vh.h_01,
vh.h_02,
vh.h_03,
ROW_NUMBER() OVER(PARTITION BY st.code_stas, st.nom_station ORDER BY vh.date_val_hor DESC) AS DISTINCT_FLG
FROM
n_station st,
val_horaire vh
WHERE
st.code_stas = vh.code_mesure
)
WHERE DISTINCT_FLG = 1
Something like this (?):
SELECT st.code_stas, st.nom_station, zzz.MAX_date_val_hor, vh.h_01, vh.h_02, vh.h_03
FROM (SELECT code_mesure, MAX(date_val_hor) AS MAX_date_val_hor FROM val_horaire GROUP BY code_mesure) ZZZ
INNER JOIN
n_station st ON st.code_stas=zzz.code_mesure
INNER JOIN val_horaire vh
ON st.code_stas = vh.code_mesure
GROUP BY st.code_stas, st.nom_station, zzz.MAX_date_val_hor, vh.h_01, vh.h_02, vh.h_03;

How to count records by week from specific data frame using SQL Query

Start Date: 10/14/2016
End Date: Statdate - 4 Weeks
I need a single query that does this sequence in SQL
SELECT COUNT(*) FROM TableName
WHERE AddDate between '10/14/2016 10:16:00' and '10/14/2016 10:31:00'
SELECT COUNT(*) FROM TableName
WHERE AddDate between '10/07/2016 10:16:00' and '10/07/2016 10:31:00'
SELECT COUNT(*) FROM TableName
WHERE AddDate between '09/30/2016 10:16:00' and '09/30/2016 10:31:00'
SELECT COUNT(*) FROM TableName
WHERE AddDate between '09/23/2016 10:16:00' and '09/23/2016 10:31:00'
I would appreciate if someone help on this.
How about something like this (for MySQL, but similar exists for other DBs)
SELECT
DATE(AddDate) as TheDate,
COUNT(*) as Records
FROM TableName
WHERE
AddDate BETWEEN '2016-23-09' AND '2016-10-15'
AND DAYOFWEEK(AddDate) = 1 //for SUNDAYS
AND TIME(AddDate) BETWEEN '10:16:00' AND '10:31:00'
GROUP BY DATE(AddDate)
ORDER BY DATE(AddDate) ASC
I haven't tested this, but it should give you something like:
TheDates Records
--------------------
2016-09-23 120
2016-09-30 157
...etc
Can't you just use UNION to put them all together? Or are you asking for something else?
SELECT COUNT(*) FROM TableName
WHERE AddDate between '10/14/2016 10:16:00' and '10/14/2016 10:31:00'
UNION
SELECT COUNT(*) FROM TableName
WHERE AddDate between '10/07/2016 10:16:00' and '10/07/2016 10:31:00'
UNION
SELECT COUNT(*) FROM TableName
WHERE AddDate between '09/30/2016 10:16:00' and '09/30/2016 10:31:00'
UNION
SELECT COUNT(*) FROM TableName
WHERE AddDate between '09/23/2016 10:16:00' and '09/23/2016 10:31:00'
Use Group by
SELECT
LEFT(DATENAME(wk,AddDate),2) as WeekNumber ,
COUNT(*) as Count
FROM TableName
WHERE AddDate between '09/23/2016 10:16:00' and '10/14/2016 10:31:00'
GROUP BY LEFT(DATENAME(wk,AddDate),2)
Here is one way using CASE statement
SELECT ranges,count(*)
FROM (SELECT CASE
WHEN AddDate BETWEEN '10/14/2016 10:16:00' AND '10/14/2016 10:31:00' THEN '10/14/2016 10:16:00 - 10/14/2016 10:31:00'
WHEN AddDate BETWEEN '10/07/2016 10:16:00' AND '10/07/2016 10:31:00' THEN '10/07/2016 10:16:00 - 10/07/2016 10:31:00'
WHEN AddDate BETWEEN '09/30/2016 10:16:00' AND '09/30/2016 10:31:00' THEN '09/30/2016 10:16:00 - 09/30/2016 10:31:00'
WHEN AddDate BETWEEN '09/23/2016 10:16:00' AND '09/23/2016 10:31:00' THEN '09/23/2016 10:16:00 - 09/23/2016 10:31:00'
END AS ranges
FROM yourtable) a
GROUP BY ranges