Select query with same value in row - sql

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
);

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

Postgres, get distinct field that has value as specified

Please see table below:
id ticket_id event
1 130 response
2 130 query
3 130 create
4 130 update
5 131 response
6 131 query
7 131 create
8 132 response
9 132 query
10 132 create
How do i return distinct ticket_id that has no 'update' (value) on event field in a postgres sql
example it should return ticket_id 131 and 132
Thanks.
You can use a NOT EXISTS condition:
select distinct t1.ticket_id
from the_table t1
where not exists (select *
from the_table t2
where t2.ticket_id = t1.ticket_id
and t2.event = 'update')

Select Data as per the given output

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

SQL Update where select top(num)

I want to UPDATE a column in the same table based on if 4 records are returned by the subquery.
This is the table structure
Id Form Quantity Transitdays percentUnderQty percentOverQty
192 0 15500 5 13950 17050
193 0 1250 5 1125 1375
194 0 5000 5 4500 5500
195 0 12500 4 11250 13750
196 0 164250 3 147825 180675
197 0 5250 3 4725 5775
198 0 6250 3 5625 6875
199 0 12250 3 11025 13475
200 0 1750 2 1575 1925
201 0 17000 2 15300 18700
202 0 2500 2 2250 2750
203 0 11500 2 10350 12650
204 0 1250 1 1125 1375
This is my attempt so far. This statement is updating all of the records and not just specific ones based on the subquery.
UPDATE Temp_Runlist
SET Form = (
SELECT MAX(Quantity) + 1 AS Form
FROM Temp_Runlist AS t2
)
WHERE EXISTS (
SELECT TOP (4) Quantity
FROM Temp_Runlist AS t1
WHERE (Quantity BETWEEN 1125 AND 1375) AND (Form = 0)
)
Logic Explanation:
I will loop over each quantity and call this query. The query should update the Form column with values starting at 1. In the query example below the result should be that the query would not update form because the subquery only found 2 matching records. If the subquery returned 4 records then the Form column of those 4 records would be 1. On the next pass then form would be 2 if only the subquery returns four matches.
Maybe there's a better way, but I think it would be easiest to use a temp table to hold the ids you want to update and use more than one statement. For example:
WITH CTE AS (
SELECT TOP (4) Id
FROM Temp_Runlist AS t1
WHERE (Quantity BETWEEN 1125 AND 1375) AND (Form = 0)
)
SELECT Id INTO #tmpIDs FROM CTE;
GO
IF (SELECT COUNT(Id) FROM #tmpIDs) = 4
BEGIN
UPDATE Temp_Runlist
SET Form = (
SELECT MAX(Form) + 1 AS Form
FROM Temp_Runlist AS t2
)
WHERE Id IN (SELECT Id FROM #tmpIDs)
END;
GO
DROP TABLE #tmpIDs
GO
The CTE gathers the records you want.
The IF checks to see if there are actually 4 records.
Then the UPDATE uses the temp table of Ids to limit.
BTW - your example had MAX(Quantity), when it looks like it should be MAX(Form).

SELECT clause with SUM condition

Have this table :
//TEST
NUMBER TOTAL
----------------------------
1 158
2 355
3 455
//TEST1
NUMBER QUANTITY UNITPRICE
--------------------------------------------
1 3 5
1 3 6
1 3 4
2 4 8
3 5 4
I used following query:
SELECT t.NUMBER,sum(t.TOTAL),NVL(SUM(t2.quantity*t2.unitprice),0)
FROM test t INNER JOIN test1 t2 ON t.NUMBER=t2.NUMBER
GROUP BY t.NUMBER;
OUTPUT:
NUMBER SUM(TOTAL) SUM(t2.quantity*t2.unitprice)
-----------------------------------------------------------
1 474 45 <--- only this wrong
2 355 32
It seem like loop for three times so 158*3 in the record.
EXPECTED OUTPUT:
NUMBER SUM(TOTAL) SUM(t2.quantity*t2.unitprice)
-----------------------------------------------------------
1 158 45
2 355 32
You have to understand that the result of your join is something like this:
//TEST1
NUMBER QUANTITY UNITPRICE TOTAL
--------------------------------------------------------------
1 3 5 158
1 3 6 158
1 3 4 158
2 4 8 355
3 5 4 455
It means you don't need to apply a SUM on TOTAL
SELECT t.NUMBER,t.TOTAL,NVL(SUM(t2.quantity*t2.unitprice),0)
FROM test t INNER JOIN test1 t2 ON t.NUMBER=t2.NUMBER
GROUP BY t.NUMBER, t.TOTAL;
Something like this should work using a subquery separating the sums:
select t.num,
sum(t.total),
test1sum
from test t
join (
select num, sum(qty*unitprice) test1sum
from test1
group by num
) t2 on t.num = t2.num
group by t.num, test1sum
SQL Fiddle Demo
In regards to your sample data, you may not even need the additional group by on the test total field. If that table only contains distinct ids, then this would work the same:
select t.num,
t.total,
sum(qty*unitprice)
from test t
join test1 t2 on t.num = t2.num
group by t.num, t.total