I am trying to organize my SQL data based off of the dates from which the orders were made.
My data:
SELECT DISTINCT ORDER_NO, ITEM, VERSION_NO,
(CASE WHEN ROW_NUMBER() OVER (PARTITION BY ORDER_NO ORDER BY NOT_BEFORE_DATE
ASC) = 1
THEN 'what-if'
ELSE 'wh'
END) AS VERSION_NEW
,
(CASE WHEN ROW_NUMBER() OVER (PARTITION BY ORDER_NO ORDER BY
NOT_BEFORE_DATE ASC) = 2
THEN 'initial'
ELSE 'other'
END) AS VERSION
FROM FDT_MAPTOOL
WHERE ITEM IN (1032711)
;
My results:
I want my data to be ordered by PO# and the date it was created.
As you can see in my picture the First two line have the same ITEM and same PO (Order_No). I need the first two to say Initial on the side because they are the first two based on the dates. They were created first. Everything after should say other.
I am not sure if PL/SQL is needed for this?
Thank you!
Use a different analytic function so that more than one row can have the value of 1 e.g.
SELECT DISTINCT ORDER_NO, ITEM, VERSION_NO,
(CASE WHEN DENSE_RANK() OVER (PARTITION BY ORDER_NO ORDER BY NOT_BEFORE_DATE
ASC) = 1
THEN 'what-if'
ELSE 'wh'
END) AS VERSION_NEW
,
(CASE WHEN DENSE_RANK() OVER (PARTITION BY ORDER_NO ORDER BY
NOT_BEFORE_DATE ASC) = 1
THEN 'initial'
ELSE 'other'
END) AS VERSION
FROM FDT_MAPTOOL
WHERE ITEM IN (1032711)
;
Either rank() OR dense_rank() should work here instead of row_number()
nb: note sure if you really need "select distinct"
Related
I have a table similar to this. If there is a confirmed record, I want to select the oldest record and if not, select the most recent one. In this case, I would want the 4_A record.
ID
Record
Type
Date
1_A
1
auto
4/7/2021
2_A
1
confirmed
4/1/2021
3_A
1
suggested
4/5/2021
4_A
1
confirmed
4/2/2021
5_A
1
suggested
4/5/2021
I've been able to use the a window function and QUALIFY to filter the most recent one but not sure how to include the TYPE field into the mix.
SELECT * from TABLE WHERE QUALIFY ROW_NUMBER() OVER (PARTITION BY RECORD ORDER BY RECORD,DATE DESC) = 1 ;
Let me assume that you mean the oldest confirmed date if there is a confrimed:
SELECT *
FROM TABLE
WHERE QUALIFY ROW_NUMBER() OVER (PARTITION BY RECORD
ORDER BY (CASE WHEN Type = 'Confirmed' THEN 1 ELSE 2 END),
(CASE WHEN Type = 'Confirmed' THEN DATE END) ASC,
DATE ASC
) = 1;
If you really mean the oldest date if there is a confirmed, then:
SELECT *
FROM TABLE
QUALIFY (CASE WHEN COUNT_IF( Type = 'Confirmed') OVER (PARTITION BY RECORD)
THEN ROW_NUMBER() OVER (PARTITION BY RECORD ORDER BY DATE)
THEN ROW_NUMBER() OVER (PARTITION BY RECORD ORDER BY DATE DESC)
END) = 1;
I am trying to complete the following:
Old situation
What I want
For a fixed maximum number of target columns, you can use window functions and conditional aggregation:
select customer,
max(case when rn = 1 then order_date end) as order_date_1,
max(case when rn = 2 then order_date end) as order_date_2,
max(case when rn = 3 then order_date end) as order_date_3
from (
select t.*, row_number() over(partition by customer order by order_date) rn
from mytable t
) t
group by customer
I apologize if there is an existing solution, I tried searching quite a bit but couldnt find much.
Here's what I am trying to do:
I have a table that resembles the first image. I want it to look like the second image. Basically every time rnk_address = 1, I want that row's order_date to be moved into a separate column for that associated user_id.
I'm ultimately trying to calculate the average difference in order_date between all rnk_address = 1, by user_id.
I added a user_counter column using rank because I imagine I will need to do some time of join where i do user_rank = user_rank + 1? But not sure....
Original table:
End result:
You can use conditional aggregation:
select user_id, first_name,
max(case when seqnum = 1 then order_date end) as order_date_1,
max(case when seqnum = 2 then order_date end) as order_date_2,
max(case when seqnum = 3 then order_date end) as order_date_3
from (select t.*,
row_number() over (partition by user_id order by order_date) as seqnum
from t
where rnk_address = 1
) t
group by user_id, first_name;
I am using the #standardsql in bigquery and trying to code the maksimum ranking of each customer_id as 1, and the rest of it are 0
This is the query result so far
The query for ranking is this
ROW_NUMBER() OVER(PARTITION BY customer_id ORDER BY booking_date Asc) as ranking
What i need is to create another column like this where it decode the maximum ranking of each customerid as 1, and the number below it as 0 just like the below table
Thanks
Based on your sample data, your ranking is unstable, because you have multiple rows with the same key values. In any case, you can still do what you want without subqueries, just using case:
select t.*,
row_number() over (partition by customer_id order by booking_date asc) as ranking,
(case when row_number() over (partition by customer_id order by booking_date asc) =
count(*) over (partition by customer_id)
then 1 else 0
end) as custom_coded
from t;
A more traditional way of doing essentially the same thing would be to use a descending sort:
select t.*,
row_number() over (partition by customer_id order by booking_date asc) as ranking,
(case when row_number() over (partition by customer_id order by booking_date desc) = 1
then 1 else 0
end) as custom_coded
from t;
We can wrap your current query, and then use MAX as an analytic function with a partition by customer to compare each ranking value against the max ranking for each customer. When the ranking value equals the maximum value for a customer, then we assign 1 for the custom_coded, otherwise we assign 0.
SELECT
customer_id, item_bought, booking_date, ranking,
CASE WHEN ranking = MAX(ranking) OVER (PARTITION BY customer_id)
THEN 1 ELSE 0 END AS custom_coded
FROM
(
SELECT customer_id, item_bought, booking_date,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY booking_date) ranking
FROM yourTable
) t;
Goal: Take the current row of the table and find the most recent item of that customer and append that item data in the next column. If the most recent item is the item 1 of that row then it should proceed to the next row. The logic should always go the the very first row of that customer. Order is based on Transaction Date and partitioned by customer ID. Example of base data provided below in addition to what the desired result set should look like after running the script.
Restrictions: I need this script to work in a CRM tool. Specifically Aprimo/CIM by teradata. With that being said I cannot use CTEs (With) or volatile tables. I also do not want to create multiple joins into itself because of the table volume.
What I have done Thus Far: I feel that the best approach may be to utilize the Window Function, but finding myself creating a lot of nested case statements. I really wanted to know if there was a better way to get the answer i am looking for. I might have to just suck it up and do a join into itself.
Base table
Desired Result Set
Quick Start Base Table:
CREATE VOLATILE TABLE Base
(
customer_id int
, trans_date date
, item varchar(1)
) ON COMMIT PRESERVE ROWS;
Insert Into Base (123,'2017-01-01','A');
Insert Into Base (123,'2017-01-02','B');
Insert Into Base (123,'2017-01-03','C');
Insert Into Base (123,'2017-01-04','D');
Insert Into Base (123,'2017-01-05','E');
Insert Into Base (999,'2017-01-06','F');
Insert Into Base (999,'2017-01-07','G');
Insert Into Base (999,'2017-01-08','H');
There's some CASEs, but not lots :-)
SELECT
dt.*,
CASE
WHEN rn = 1
THEN Min(CASE WHEN rn = 2 THEN item end) Over (PARTITION BY customer_id)
ELSE Min(CASE WHEN rn = 1 THEN item end) Over (PARTITION BY customer_id)
END,
CASE
WHEN rn <=2
THEN Min(CASE WHEN rn = 3 THEN item end) Over (PARTITION BY customer_id)
ELSE Min(CASE WHEN rn = 2 THEN item end) Over (PARTITION BY customer_id)
END,
CASE
WHEN rn <= 3
THEN Min(CASE WHEN rn = 4 THEN item end) Over (PARTITION BY customer_id)
ELSE Min(CASE WHEN rn = 3 THEN item end) Over (PARTITION BY customer_id)
END
FROM
(
SELECT
Row_Number() Over (PARTITION BY customer_id ORDER BY trans_date) AS rn
,base.*
FROM Base
) AS dt
ORDER BY customer_id, trans_date