Select Data as per the given output - sql

Table 1:
ID
CALLID
CALLSTATUS
1
123
Generated
2
321
Not Generated
3
343
Generated
4
567
Not Generated
5
789
Generated
Table 2:
UID
ID
CALLID
GENERATEDATE
RESULT
11
1
123
2021/3/18
1
21
1
123
2021/4/20
1
31
1
123
2021/5/20
0
41
2
321
NULL
NULL
51
3
343
2021/4/21
1
61
4
567
NULL
NULL
71
5
789
2021/5/1
0
Output of Oracle should be like below table:
ID
CALLID
GENERATEDATE
CALLSTATUS
RESULT
1
123
2021/4/20
Generated
1
2
321
NULL
Not Generated
NULL
3
343
2021/4/21
Generated
1
4
567
NULL
Not Generated
NULL
5
789
2021/5/1
Generated
0
The output which I want should be like above table. For CALLID '123', as per table 2 last generated call is on '2021/5/20' but it's result is '0' which i don't want to select. It should select '2021/4/21' because it's result is '1'. But for CALLID '789', No RESULT is '1' so it should select Generated Date as '2021/5/1'.

You can use conditional aggregation along with NVL() function depending on the values for the result column such as
SELECT t1.id, MAX(t1.callid) AS callid,
NVL(MAX(CASE WHEN result = 1 THEN t2.generatedate END),
MAX(CASE WHEN NVL(result,0)!=1 THEN t2.generatedate END)) AS generateddate,
MAX(t1.callstatus) AS callstatus, MAX(result) AS result
FROM Table1 t1
JOIN Table2 t2
ON t2.id = t1.id
AND t2.callid = t1.callid
GROUP BY t1.id
ORDER BY t1.id
ID
CALLID
GENERATEDDATE
CALLSTATUS
RESULT
1
123
20/04/2021
Generated
1
2
321
Not Generated
3
343
21/04/2021
Generated
1
4
567
Not Generated
5
789
01/05/2021
Generated
0
Demo

Related

SQL, label user based on the similarity

Is below case possible in SQL?
Let say I have a table like this:
user_id
product_id
1
123
1
122
1
121
2
124
2
125
2
121
3
123
3
122
3
122
4
123
4
212
4
222
5
124
5
125
5
121
I want to label the user if they have same product_id, regardless the order, so the output looks like this:
user_id
product_id
label
1
123
a
1
122
a
1
121
a
2
124
b
2
125
b
2
121
b
3
123
a
3
121
a
3
122
a
4
123
c
4
212
c
4
222
c
5
124
b
5
125
b
5
121
b
Please advise
You can use the string_agg function to get the list of product_ids for each user (as a single string), then use the dense_rank function on that string to get unique labels for each product_ids list.
select T.user_id, T.product_id, D.label
from table_name T join
(
select user_id,
chr(dense_rank() over (order by user_products) + 96) label
from
(
select user_id,
string_agg(cast(product_id as string), ',' order by product_id) user_products
from table_name
group by user_id
) lbl
) D
on T.user_id = D.user_id
order by T.user_id

Select query with same value in row

I have a table structure like this:
order_item_id order_id product_id
1 513 120
2 213 121
3 513 120
4 312 131
5 312 131
6 102 123
I want to have a SQL query where I can get the following results:
order_item_id order_id product_id
1 513 120
3 513 120
4 312 131
5 312 131
I used the following SQL query to fetch the results, but it doesn't help:
SELECT *
FROM `stg_83087_wc_order_product_lookup`
WHERE `order_id` = `order_id` and `product_id` = `product_id`
The only question I have to is to get the next value of the row so I can make the comparison here.
You basically need to check the existance of similar rows:
select *
from t
where exists (
select * from t t2
where t2.order_id = t.order_id
and t2.product_id = t.product_id
and t2.order_item_id != t.order_item_id
);

How to find values of column status that have 8 but still do not have 9

Iam working on project and i need to find in table one column named status (this col have values from 1-12), i want to find all values that below to the condition (if the status have 8 but still do not have 9), for more information :
Original table :
File_name id status Execution_number
Live_package1.zip 333 3 4444443434343
Live_package2.zip 444 7 8888888886767
Live_package1.zip 333 8 4444443434343
Live_package2.zip 444 8 8888888886767
Live_package2.zip 444 10 8888888886767
Live_package3.zip 666 8 9999999999999
Live_package4.zip 111 9 3333333333333
The desired result
File_name id status Execution_number
Live_package1.zip 333 8 4444443434343
Live_package3.zip 666 8 9999999999999
iam using the following code , but I did not received the result what I expected:
SELECT *
FROM tbl_doc_state
WHERE status =8
AND NOT(status !=9);
If you want to exclude rows that have status 8 but there are other rows with the same id but with the status 9, use a not exists condition:
SELECT t1.*
FROM tbl_doc_state t1
WHERE status = 8
and not exists (select *
from tbl_doc_state t2
where t2.id = t1.id
and t2.status >= 9);
Something like this?
SQL> select * From tbl_doc_state;
FIL ID STATUS EXECUTION_NUMBER
--- ---------- ---------- ----------------
lp1 333 3 43
lp2 444 7 67
lp1 333 8 43
lp2 444 10 67
lp3 666 8 99
lp4 111 9 33
6 rows selected.
SQL> with temp as
2 (select id,
3 max(status) max_status
4 from tbl_doc_state
5 group by id
6 )
7 select a.*
8 from tbl_doc_state a join temp t on a.id = t.id
9 and a.status = t.max_status
10 where t.max_status = 8;
FIL ID STATUS EXECUTION_NUMBER
--- ---------- ---------- ----------------
lp1 333 8 43
lp3 666 8 99
SQL>
You don't tell which column should used to order the records. If you are using status for this, then the query is just:
select * from tbl_doc_state where status = 8
If you have another ordering column, say sort_id, then the question makes more sense. You can use window functions:
select t.*
from (
select t.*, max(case when status = 9 then 1 else 0 end) over(partition by id order by sort_id) has_status_9
from mytable t
) t
where status = 8 and has_status_9 = 0
With window function MAX():
select t.File_name, t.id, t.status, t.Execution_number
from (
select t.*, max(t.status) over(partition by t.id) max_status
from tbl_doc_state t
) t
where max_status = 8 and status = max_status
See the demo.
Results:
> File_name | id | status | Execution_number
> :---------------- | --: | -----: | :---------------
> Live_package1.zip | 333 | 8 | 4444443434343
> Live_package3.zip | 666 | 8 | 9999999999999

SQL Select Distinct based on Conditional

Assumptions:
ITEM STATUS in STAGINGLINE: 0 - NOT STARTED, 1 - VERIFIED, 2 - MISCOUNT
Want only one line to show per ASN so easiest way is using DISTINCT....
SELECT DISTINCT ASN, STATUS
FROM STAGINGLINE
However, I can't use a simple distinct because of the multiple STATUS possibilities, you would get multiples for each status.
Result set should show only 2 “ASNs”: 123 and 343
Example STAGINGLINE Table
Case 1:
(ASN #, ITEM #, STATUS, QTY ,ACTUAL)
123 898 0 4 NULL
123 344 0 9 NULL
123 123 0 2 NULL
123 534 0 1 NULL
343 111 1 6 6
ResultSet needs to be:
123 NOT STARTED (because all 0)
343 VERIFIED
Case 2:
(ASN #, ITEM #, STATUS, QTY ,ACTUAL)
123 898 1 4 4
123 344 0 9 NULL
123 123 0 2 NULL
123 534 0 1 NULL
ResultSet needs to be:
123 IN PROGRESS (because at least one of them is not in a 0 STATUS)
343 VERIFIED
Case 3:
(ASN #, ITEM #, STATUS, QTY ,ACTUAL)
123 898 1 4 4
123 344 2 9 5 <- MISCOUNT
123 123 0 2 NULL
123 534 0 1 NULL
ResultSet needs to be:
123 MISCOUNT (because of the existence of a 2 in at least one of the STATUS column)
343 VERIFIED
Case 4:
(ASN #, ITEM #, STATUS, QTY ,ACTUAL)
123 898 1 4 4
123 344 1 9 9
123 123 1 2 2
123 534 1 1 1
ResultSet needs to be:
123 VERIFIED (because all are STATUS of 1)
343 VERIFIED
Are you looking for max():
select asn, max(status)
from t
group by asn;
Or perhaps max() with case:
select (case max(status) when 0 then 'NOT STARTED'
when 1 then 'VERIFIED'
when 2 then 'MISCOUNT'
end)
from t
group by asn;
EDIT:
The rules seem a bit more detailed:
select (case when max(status) = 0 then 'NOT STARTED'
when max(status) = 1 and min(status) = max(status) then 'VERIFIED'
when max(status) = 2 then 'MISCOUNT'
else 'IN PROGRESS'
end)
from t
group by asn;
Can you try this,
SELECT ASN,
CASE WHEN MAX_STATUS = 2 THEN 'MISCOUNT'
WHEN MAX_STATUS = 0 THEN 'NOT STARTED'
WHEN MAX_STATUS = 1 AND MIN_STATUS = 1 THEN 'VERIFIED'
WHEN MAX_STATUS = 1 AND MIN_STATUS = 0 THEN 'IN-PROGRESS'
END STATUS
FROM
(SELECT ASN, MAX(STATUS) MAX_STATUS, MIN(STATS) MIN_STATUS
FROM STAGELINE
GROUP BY ASN) A

SQL Server: SELECT value with multiple criteria

Looking for a SQL solution to the following problem
Return USER and NUMBER combination WHERE PRIORITY = MIN(PRIORITY) [NULL is equivalent to MAX(PRIORITY + 1)] ... in the case of ties in PRIORITY, break using lowest LINEITEM
FIELDS:
USER,
LINEITEM,
NUMBER,
PRIORITY
VALUES: ('X' signifies desired combination)
USER LINEITEM NUMBER PRIORITY
-------------------------------------
1 1 12345 NULL
1 2 23456 2
1 3 34567 1 X
2 1 9876 3
2 2 98765 1 X
2 3 12345 2
2 4 23456 1
3 1 23456 NULL X
3 2 12345 NULL
4 1 34567 NULL
4 2 45678 NULL
4 3 12345 1 X
4 4 12345 2
4 5 23456 1
Thanks in advance.
In response to PM 77-1,
My current method:
SELECT table1.user,table1.number
FROM table1
JOIN (
SELECT user,
CAST(MIN((COALESCE(priority,999) *
(10 ^ (5 - LEN(COALESCE(CAST(priority AS VARCHAR),'999'))))) +
lineitem) AS VARCHAR) AS selector
FROM table1 GROUP BY user
) AS table2
ON table1.user = table2.user
AND table1.lineitem = CAST(RIGHT(table2.selector, 1) AS int)
ORDER BY table1.user;
Use ROW_NUMBER:
SQL Fiddle
;WITH Cte AS(
SELECT *,
ROW_NUMBER() OVER(
PARTITION BY [User]
ORDER BY
CASE WHEN Priority IS NULL THEN 1 ELSE 0 END,
Priority,
LineItem
) AS rn
FROM tbl
)
SELECT
[User], LineItem, Number, Priority
FROM Cte
WHERE rn = 1